1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_MIPS64
6
7// Note on Mips implementation:
8//
9// The result_register() for mips is the 'v0' register, which is defined
10// by the ABI to contain function return values. However, the first
11// parameter to a function is defined to be 'a0'. So there are many
12// places where we have to move a previous result in v0 to a0 for the
13// next call: mov(a0, v0). This is not needed on the other architectures.
14
15#include "src/ast/scopes.h"
16#include "src/code-factory.h"
17#include "src/code-stubs.h"
18#include "src/codegen.h"
19#include "src/debug/debug.h"
20#include "src/full-codegen/full-codegen.h"
21#include "src/ic/ic.h"
22#include "src/parsing/parser.h"
23
24#include "src/mips64/code-stubs-mips64.h"
25#include "src/mips64/macro-assembler-mips64.h"
26
27namespace v8 {
28namespace internal {
29
30#define __ ACCESS_MASM(masm())
31
32// A patch site is a location in the code which it is possible to patch. This
33// class has a number of methods to emit the code which is patchable and the
34// method EmitPatchInfo to record a marker back to the patchable code. This
35// marker is a andi zero_reg, rx, #yyyy instruction, and rx * 0x0000ffff + yyyy
36// (raw 16 bit immediate value is used) is the delta from the pc to the first
37// instruction of the patchable code.
38// The marker instruction is effectively a NOP (dest is zero_reg) and will
39// never be emitted by normal code.
40class JumpPatchSite BASE_EMBEDDED {
41 public:
42  explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
43#ifdef DEBUG
44    info_emitted_ = false;
45#endif
46  }
47
48  ~JumpPatchSite() {
49    DCHECK(patch_site_.is_bound() == info_emitted_);
50  }
51
52  // When initially emitting this ensure that a jump is always generated to skip
53  // the inlined smi code.
54  void EmitJumpIfNotSmi(Register reg, Label* target) {
55    DCHECK(!patch_site_.is_bound() && !info_emitted_);
56    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
57    __ bind(&patch_site_);
58    __ andi(at, reg, 0);
59    // Always taken before patched.
60    __ BranchShort(target, eq, at, Operand(zero_reg));
61  }
62
63  // When initially emitting this ensure that a jump is never generated to skip
64  // the inlined smi code.
65  void EmitJumpIfSmi(Register reg, Label* target) {
66    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
67    DCHECK(!patch_site_.is_bound() && !info_emitted_);
68    __ bind(&patch_site_);
69    __ andi(at, reg, 0);
70    // Never taken before patched.
71    __ BranchShort(target, ne, at, Operand(zero_reg));
72  }
73
74  void EmitPatchInfo() {
75    if (patch_site_.is_bound()) {
76      int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
77      Register reg = Register::from_code(delta_to_patch_site / kImm16Mask);
78      __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask);
79#ifdef DEBUG
80      info_emitted_ = true;
81#endif
82    } else {
83      __ nop();  // Signals no inlined code.
84    }
85  }
86
87 private:
88  MacroAssembler* masm() { return masm_; }
89  MacroAssembler* masm_;
90  Label patch_site_;
91#ifdef DEBUG
92  bool info_emitted_;
93#endif
94};
95
96
97// Generate code for a JS function.  On entry to the function the receiver
98// and arguments have been pushed on the stack left to right.  The actual
99// argument count matches the formal parameter count expected by the
100// function.
101//
102// The live registers are:
103//   o a1: the JS function object being called (i.e. ourselves)
104//   o a3: the new target value
105//   o cp: our context
106//   o fp: our caller's frame pointer
107//   o sp: stack pointer
108//   o ra: return address
109//
110// The function builds a JS frame.  Please see JavaScriptFrameConstants in
111// frames-mips.h for its layout.
112void FullCodeGenerator::Generate() {
113  CompilationInfo* info = info_;
114  profiling_counter_ = isolate()->factory()->NewCell(
115      Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
116  SetFunctionPosition(literal());
117  Comment cmnt(masm_, "[ function compiled by full code generator");
118
119  ProfileEntryHookStub::MaybeCallEntryHook(masm_);
120
121  if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
122    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
123    __ ld(a2, MemOperand(sp, receiver_offset));
124    __ AssertNotSmi(a2);
125    __ GetObjectType(a2, a2, a2);
126    __ Check(ge, kSloppyFunctionExpectsJSReceiverReceiver, a2,
127             Operand(FIRST_JS_RECEIVER_TYPE));
128  }
129
130  // Open a frame scope to indicate that there is a frame on the stack.  The
131  // MANUAL indicates that the scope shouldn't actually generate code to set up
132  // the frame (that is done below).
133  FrameScope frame_scope(masm_, StackFrame::MANUAL);
134  info->set_prologue_offset(masm_->pc_offset());
135  __ Prologue(info->GeneratePreagedPrologue());
136
137  { Comment cmnt(masm_, "[ Allocate locals");
138    int locals_count = info->scope()->num_stack_slots();
139    // Generators allocate locals, if any, in context slots.
140    DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0);
141    OperandStackDepthIncrement(locals_count);
142    if (locals_count > 0) {
143      if (locals_count >= 128) {
144        Label ok;
145        __ Dsubu(t1, sp, Operand(locals_count * kPointerSize));
146        __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
147        __ Branch(&ok, hs, t1, Operand(a2));
148        __ CallRuntime(Runtime::kThrowStackOverflow);
149        __ bind(&ok);
150      }
151      __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
152      int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
153      if (locals_count >= kMaxPushes) {
154        int loop_iterations = locals_count / kMaxPushes;
155        __ li(a2, Operand(loop_iterations));
156        Label loop_header;
157        __ bind(&loop_header);
158        // Do pushes.
159        __ Dsubu(sp, sp, Operand(kMaxPushes * kPointerSize));
160        for (int i = 0; i < kMaxPushes; i++) {
161          __ sd(t1, MemOperand(sp, i * kPointerSize));
162        }
163        // Continue loop if not done.
164        __ Dsubu(a2, a2, Operand(1));
165        __ Branch(&loop_header, ne, a2, Operand(zero_reg));
166      }
167      int remaining = locals_count % kMaxPushes;
168      // Emit the remaining pushes.
169      __ Dsubu(sp, sp, Operand(remaining * kPointerSize));
170      for (int i  = 0; i < remaining; i++) {
171        __ sd(t1, MemOperand(sp, i * kPointerSize));
172      }
173    }
174  }
175
176  bool function_in_register_a1 = true;
177
178  // Possibly allocate a local context.
179  if (info->scope()->num_heap_slots() > 0) {
180    Comment cmnt(masm_, "[ Allocate context");
181    // Argument to NewContext is the function, which is still in a1.
182    bool need_write_barrier = true;
183    int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
184    if (info->scope()->is_script_scope()) {
185      __ push(a1);
186      __ Push(info->scope()->GetScopeInfo(info->isolate()));
187      __ CallRuntime(Runtime::kNewScriptContext);
188      PrepareForBailoutForId(BailoutId::ScriptContext(),
189                             BailoutState::TOS_REGISTER);
190      // The new target value is not used, clobbering is safe.
191      DCHECK_NULL(info->scope()->new_target_var());
192    } else {
193      if (info->scope()->new_target_var() != nullptr) {
194        __ push(a3);  // Preserve new target.
195      }
196      if (slots <= FastNewContextStub::kMaximumSlots) {
197        FastNewContextStub stub(isolate(), slots);
198        __ CallStub(&stub);
199        // Result of FastNewContextStub is always in new space.
200        need_write_barrier = false;
201      } else {
202        __ push(a1);
203        __ CallRuntime(Runtime::kNewFunctionContext);
204      }
205      if (info->scope()->new_target_var() != nullptr) {
206        __ pop(a3);  // Restore new target.
207      }
208    }
209    function_in_register_a1 = false;
210    // Context is returned in v0. It replaces the context passed to us.
211    // It's saved in the stack and kept live in cp.
212    __ mov(cp, v0);
213    __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
214    // Copy any necessary parameters into the context.
215    int num_parameters = info->scope()->num_parameters();
216    int first_parameter = info->scope()->has_this_declaration() ? -1 : 0;
217    for (int i = first_parameter; i < num_parameters; i++) {
218      Variable* var = (i == -1) ? scope()->receiver() : scope()->parameter(i);
219      if (var->IsContextSlot()) {
220        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
221                                 (num_parameters - 1 - i) * kPointerSize;
222        // Load parameter from stack.
223        __ ld(a0, MemOperand(fp, parameter_offset));
224        // Store it in the context.
225        MemOperand target = ContextMemOperand(cp, var->index());
226        __ sd(a0, target);
227
228        // Update the write barrier.
229        if (need_write_barrier) {
230          __ RecordWriteContextSlot(cp, target.offset(), a0, a2,
231                                    kRAHasBeenSaved, kDontSaveFPRegs);
232        } else if (FLAG_debug_code) {
233          Label done;
234          __ JumpIfInNewSpace(cp, a0, &done);
235          __ Abort(kExpectedNewSpaceObject);
236          __ bind(&done);
237        }
238      }
239    }
240  }
241
242  // Register holding this function and new target are both trashed in case we
243  // bailout here. But since that can happen only when new target is not used
244  // and we allocate a context, the value of |function_in_register| is correct.
245  PrepareForBailoutForId(BailoutId::FunctionContext(),
246                         BailoutState::NO_REGISTERS);
247
248  // Possibly set up a local binding to the this function which is used in
249  // derived constructors with super calls.
250  Variable* this_function_var = scope()->this_function_var();
251  if (this_function_var != nullptr) {
252    Comment cmnt(masm_, "[ This function");
253    if (!function_in_register_a1) {
254      __ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
255      // The write barrier clobbers register again, keep it marked as such.
256    }
257    SetVar(this_function_var, a1, a0, a2);
258  }
259
260  Variable* new_target_var = scope()->new_target_var();
261  if (new_target_var != nullptr) {
262    Comment cmnt(masm_, "[ new.target");
263    SetVar(new_target_var, a3, a0, a2);
264  }
265
266  // Possibly allocate RestParameters
267  int rest_index;
268  Variable* rest_param = scope()->rest_parameter(&rest_index);
269  if (rest_param) {
270    Comment cmnt(masm_, "[ Allocate rest parameter array");
271    if (!function_in_register_a1) {
272      __ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
273    }
274    FastNewRestParameterStub stub(isolate());
275    __ CallStub(&stub);
276    function_in_register_a1 = false;
277    SetVar(rest_param, v0, a1, a2);
278  }
279
280  Variable* arguments = scope()->arguments();
281  if (arguments != NULL) {
282    // Function uses arguments object.
283    Comment cmnt(masm_, "[ Allocate arguments object");
284    if (!function_in_register_a1) {
285      // Load this again, if it's used by the local context below.
286      __ ld(a1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
287    }
288    if (is_strict(language_mode()) || !has_simple_parameters()) {
289      FastNewStrictArgumentsStub stub(isolate());
290      __ CallStub(&stub);
291    } else if (literal()->has_duplicate_parameters()) {
292      __ Push(a1);
293      __ CallRuntime(Runtime::kNewSloppyArguments_Generic);
294    } else {
295      FastNewSloppyArgumentsStub stub(isolate());
296      __ CallStub(&stub);
297    }
298
299    SetVar(arguments, v0, a1, a2);
300  }
301
302  if (FLAG_trace) {
303    __ CallRuntime(Runtime::kTraceEnter);
304  }
305
306  // Visit the declarations and body.
307  PrepareForBailoutForId(BailoutId::FunctionEntry(),
308                         BailoutState::NO_REGISTERS);
309  {
310    Comment cmnt(masm_, "[ Declarations");
311    VisitDeclarations(scope()->declarations());
312  }
313
314  // Assert that the declarations do not use ICs. Otherwise the debugger
315  // won't be able to redirect a PC at an IC to the correct IC in newly
316  // recompiled code.
317  DCHECK_EQ(0, ic_total_count_);
318
319  {
320    Comment cmnt(masm_, "[ Stack check");
321    PrepareForBailoutForId(BailoutId::Declarations(),
322                           BailoutState::NO_REGISTERS);
323    Label ok;
324    __ LoadRoot(at, Heap::kStackLimitRootIndex);
325    __ Branch(&ok, hs, sp, Operand(at));
326    Handle<Code> stack_check = isolate()->builtins()->StackCheck();
327    PredictableCodeSizeScope predictable(
328        masm_, masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
329    __ Call(stack_check, RelocInfo::CODE_TARGET);
330    __ bind(&ok);
331  }
332
333  {
334    Comment cmnt(masm_, "[ Body");
335    DCHECK(loop_depth() == 0);
336
337    VisitStatements(literal()->body());
338
339    DCHECK(loop_depth() == 0);
340  }
341
342  // Always emit a 'return undefined' in case control fell off the end of
343  // the body.
344  { Comment cmnt(masm_, "[ return <undefined>;");
345    __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
346  }
347  EmitReturnSequence();
348}
349
350
351void FullCodeGenerator::ClearAccumulator() {
352  DCHECK(Smi::FromInt(0) == 0);
353  __ mov(v0, zero_reg);
354}
355
356
357void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
358  __ li(a2, Operand(profiling_counter_));
359  __ ld(a3, FieldMemOperand(a2, Cell::kValueOffset));
360  __ Dsubu(a3, a3, Operand(Smi::FromInt(delta)));
361  __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset));
362}
363
364
365void FullCodeGenerator::EmitProfilingCounterReset() {
366  int reset_value = FLAG_interrupt_budget;
367  if (info_->is_debug()) {
368    // Detect debug break requests as soon as possible.
369    reset_value = FLAG_interrupt_budget >> 4;
370  }
371  __ li(a2, Operand(profiling_counter_));
372  __ li(a3, Operand(Smi::FromInt(reset_value)));
373  __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset));
374}
375
376
377void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
378                                                Label* back_edge_target) {
379  // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need
380  // to make sure it is constant. Branch may emit a skip-or-jump sequence
381  // instead of the normal Branch. It seems that the "skip" part of that
382  // sequence is about as long as this Branch would be so it is safe to ignore
383  // that.
384  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
385  Comment cmnt(masm_, "[ Back edge bookkeeping");
386  Label ok;
387  DCHECK(back_edge_target->is_bound());
388  int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
389  int weight = Min(kMaxBackEdgeWeight,
390                   Max(1, distance / kCodeSizeMultiplier));
391  EmitProfilingCounterDecrement(weight);
392  __ slt(at, a3, zero_reg);
393  __ beq(at, zero_reg, &ok);
394  // Call will emit a li t9 first, so it is safe to use the delay slot.
395  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
396  // Record a mapping of this PC offset to the OSR id.  This is used to find
397  // the AST id from the unoptimized code in order to use it as a key into
398  // the deoptimization input data found in the optimized code.
399  RecordBackEdge(stmt->OsrEntryId());
400  EmitProfilingCounterReset();
401
402  __ bind(&ok);
403  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
404  // Record a mapping of the OSR id to this PC.  This is used if the OSR
405  // entry becomes the target of a bailout.  We don't expect it to be, but
406  // we want it to work if it is.
407  PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
408}
409
410void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
411    bool is_tail_call) {
412  // Pretend that the exit is a backwards jump to the entry.
413  int weight = 1;
414  if (info_->ShouldSelfOptimize()) {
415    weight = FLAG_interrupt_budget / FLAG_self_opt_count;
416  } else {
417    int distance = masm_->pc_offset();
418    weight = Min(kMaxBackEdgeWeight, Max(1, distance / kCodeSizeMultiplier));
419  }
420  EmitProfilingCounterDecrement(weight);
421  Label ok;
422  __ Branch(&ok, ge, a3, Operand(zero_reg));
423  // Don't need to save result register if we are going to do a tail call.
424  if (!is_tail_call) {
425    __ push(v0);
426  }
427  __ Call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET);
428  if (!is_tail_call) {
429    __ pop(v0);
430  }
431  EmitProfilingCounterReset();
432  __ bind(&ok);
433}
434
435void FullCodeGenerator::EmitReturnSequence() {
436  Comment cmnt(masm_, "[ Return sequence");
437  if (return_label_.is_bound()) {
438    __ Branch(&return_label_);
439  } else {
440    __ bind(&return_label_);
441    if (FLAG_trace) {
442      // Push the return value on the stack as the parameter.
443      // Runtime::TraceExit returns its parameter in v0.
444      __ push(v0);
445      __ CallRuntime(Runtime::kTraceExit);
446    }
447    EmitProfilingCounterHandlingForReturnSequence(false);
448
449    // Make sure that the constant pool is not emitted inside of the return
450    // sequence.
451    { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
452      // Here we use masm_-> instead of the __ macro to avoid the code coverage
453      // tool from instrumenting as we rely on the code size here.
454      int32_t arg_count = info_->scope()->num_parameters() + 1;
455      int32_t sp_delta = arg_count * kPointerSize;
456      SetReturnPosition(literal());
457      masm_->mov(sp, fp);
458      masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit()));
459      masm_->Daddu(sp, sp, Operand(sp_delta));
460      masm_->Jump(ra);
461    }
462  }
463}
464
465void FullCodeGenerator::RestoreContext() {
466  __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
467}
468
469void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
470  DCHECK(var->IsStackAllocated() || var->IsContextSlot());
471  codegen()->GetVar(result_register(), var);
472  codegen()->PushOperand(result_register());
473}
474
475
476void FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const {
477}
478
479
480void FullCodeGenerator::AccumulatorValueContext::Plug(
481    Heap::RootListIndex index) const {
482  __ LoadRoot(result_register(), index);
483}
484
485
486void FullCodeGenerator::StackValueContext::Plug(
487    Heap::RootListIndex index) const {
488  __ LoadRoot(result_register(), index);
489  codegen()->PushOperand(result_register());
490}
491
492
493void FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const {
494  codegen()->PrepareForBailoutBeforeSplit(condition(),
495                                          true,
496                                          true_label_,
497                                          false_label_);
498  if (index == Heap::kUndefinedValueRootIndex ||
499      index == Heap::kNullValueRootIndex ||
500      index == Heap::kFalseValueRootIndex) {
501    if (false_label_ != fall_through_) __ Branch(false_label_);
502  } else if (index == Heap::kTrueValueRootIndex) {
503    if (true_label_ != fall_through_) __ Branch(true_label_);
504  } else {
505    __ LoadRoot(result_register(), index);
506    codegen()->DoTest(this);
507  }
508}
509
510
511void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
512}
513
514
515void FullCodeGenerator::AccumulatorValueContext::Plug(
516    Handle<Object> lit) const {
517  __ li(result_register(), Operand(lit));
518}
519
520
521void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
522  // Immediates cannot be pushed directly.
523  __ li(result_register(), Operand(lit));
524  codegen()->PushOperand(result_register());
525}
526
527
528void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
529  codegen()->PrepareForBailoutBeforeSplit(condition(),
530                                          true,
531                                          true_label_,
532                                          false_label_);
533  DCHECK(lit->IsNull(isolate()) || lit->IsUndefined(isolate()) ||
534         !lit->IsUndetectable());
535  if (lit->IsUndefined(isolate()) || lit->IsNull(isolate()) ||
536      lit->IsFalse(isolate())) {
537    if (false_label_ != fall_through_) __ Branch(false_label_);
538  } else if (lit->IsTrue(isolate()) || lit->IsJSObject()) {
539    if (true_label_ != fall_through_) __ Branch(true_label_);
540  } else if (lit->IsString()) {
541    if (String::cast(*lit)->length() == 0) {
542      if (false_label_ != fall_through_) __ Branch(false_label_);
543    } else {
544      if (true_label_ != fall_through_) __ Branch(true_label_);
545    }
546  } else if (lit->IsSmi()) {
547    if (Smi::cast(*lit)->value() == 0) {
548      if (false_label_ != fall_through_) __ Branch(false_label_);
549    } else {
550      if (true_label_ != fall_through_) __ Branch(true_label_);
551    }
552  } else {
553    // For simplicity we always test the accumulator register.
554    __ li(result_register(), Operand(lit));
555    codegen()->DoTest(this);
556  }
557}
558
559
560void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
561                                                       Register reg) const {
562  DCHECK(count > 0);
563  if (count > 1) codegen()->DropOperands(count - 1);
564  __ sd(reg, MemOperand(sp, 0));
565}
566
567
568void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
569                                            Label* materialize_false) const {
570  DCHECK(materialize_true == materialize_false);
571  __ bind(materialize_true);
572}
573
574
575void FullCodeGenerator::AccumulatorValueContext::Plug(
576    Label* materialize_true,
577    Label* materialize_false) const {
578  Label done;
579  __ bind(materialize_true);
580  __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
581  __ Branch(&done);
582  __ bind(materialize_false);
583  __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
584  __ bind(&done);
585}
586
587
588void FullCodeGenerator::StackValueContext::Plug(
589    Label* materialize_true,
590    Label* materialize_false) const {
591  codegen()->OperandStackDepthIncrement(1);
592  Label done;
593  __ bind(materialize_true);
594  __ LoadRoot(at, Heap::kTrueValueRootIndex);
595  // Push the value as the following branch can clobber at in long branch mode.
596  __ push(at);
597  __ Branch(&done);
598  __ bind(materialize_false);
599  __ LoadRoot(at, Heap::kFalseValueRootIndex);
600  __ push(at);
601  __ bind(&done);
602}
603
604
605void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
606                                          Label* materialize_false) const {
607  DCHECK(materialize_true == true_label_);
608  DCHECK(materialize_false == false_label_);
609}
610
611
612void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const {
613  Heap::RootListIndex value_root_index =
614      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
615  __ LoadRoot(result_register(), value_root_index);
616}
617
618
619void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
620  Heap::RootListIndex value_root_index =
621      flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
622  __ LoadRoot(at, value_root_index);
623  codegen()->PushOperand(at);
624}
625
626
627void FullCodeGenerator::TestContext::Plug(bool flag) const {
628  codegen()->PrepareForBailoutBeforeSplit(condition(),
629                                          true,
630                                          true_label_,
631                                          false_label_);
632  if (flag) {
633    if (true_label_ != fall_through_) __ Branch(true_label_);
634  } else {
635    if (false_label_ != fall_through_) __ Branch(false_label_);
636  }
637}
638
639
640void FullCodeGenerator::DoTest(Expression* condition,
641                               Label* if_true,
642                               Label* if_false,
643                               Label* fall_through) {
644  __ mov(a0, result_register());
645  Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
646  CallIC(ic, condition->test_id());
647  __ LoadRoot(at, Heap::kTrueValueRootIndex);
648  Split(eq, result_register(), Operand(at), if_true, if_false, fall_through);
649}
650
651
652void FullCodeGenerator::Split(Condition cc,
653                              Register lhs,
654                              const Operand&  rhs,
655                              Label* if_true,
656                              Label* if_false,
657                              Label* fall_through) {
658  if (if_false == fall_through) {
659    __ Branch(if_true, cc, lhs, rhs);
660  } else if (if_true == fall_through) {
661    __ Branch(if_false, NegateCondition(cc), lhs, rhs);
662  } else {
663    __ Branch(if_true, cc, lhs, rhs);
664    __ Branch(if_false);
665  }
666}
667
668
669MemOperand FullCodeGenerator::StackOperand(Variable* var) {
670  DCHECK(var->IsStackAllocated());
671  // Offset is negative because higher indexes are at lower addresses.
672  int offset = -var->index() * kPointerSize;
673  // Adjust by a (parameter or local) base offset.
674  if (var->IsParameter()) {
675    offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
676  } else {
677    offset += JavaScriptFrameConstants::kLocal0Offset;
678  }
679  return MemOperand(fp, offset);
680}
681
682
683MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
684  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
685  if (var->IsContextSlot()) {
686    int context_chain_length = scope()->ContextChainLength(var->scope());
687    __ LoadContext(scratch, context_chain_length);
688    return ContextMemOperand(scratch, var->index());
689  } else {
690    return StackOperand(var);
691  }
692}
693
694
695void FullCodeGenerator::GetVar(Register dest, Variable* var) {
696  // Use destination as scratch.
697  MemOperand location = VarOperand(var, dest);
698  __ ld(dest, location);
699}
700
701
702void FullCodeGenerator::SetVar(Variable* var,
703                               Register src,
704                               Register scratch0,
705                               Register scratch1) {
706  DCHECK(var->IsContextSlot() || var->IsStackAllocated());
707  DCHECK(!scratch0.is(src));
708  DCHECK(!scratch0.is(scratch1));
709  DCHECK(!scratch1.is(src));
710  MemOperand location = VarOperand(var, scratch0);
711  __ sd(src, location);
712  // Emit the write barrier code if the location is in the heap.
713  if (var->IsContextSlot()) {
714    __ RecordWriteContextSlot(scratch0,
715                              location.offset(),
716                              src,
717                              scratch1,
718                              kRAHasBeenSaved,
719                              kDontSaveFPRegs);
720  }
721}
722
723
724void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
725                                                     bool should_normalize,
726                                                     Label* if_true,
727                                                     Label* if_false) {
728  // Only prepare for bailouts before splits if we're in a test
729  // context. Otherwise, we let the Visit function deal with the
730  // preparation to avoid preparing with the same AST id twice.
731  if (!context()->IsTest()) return;
732
733  Label skip;
734  if (should_normalize) __ Branch(&skip);
735  PrepareForBailout(expr, BailoutState::TOS_REGISTER);
736  if (should_normalize) {
737    __ LoadRoot(a4, Heap::kTrueValueRootIndex);
738    Split(eq, a0, Operand(a4), if_true, if_false, NULL);
739    __ bind(&skip);
740  }
741}
742
743
744void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
745  // The variable in the declaration always resides in the current function
746  // context.
747  DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
748  if (FLAG_debug_code) {
749    // Check that we're not inside a with or catch context.
750    __ ld(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
751    __ LoadRoot(a4, Heap::kWithContextMapRootIndex);
752    __ Check(ne, kDeclarationInWithContext,
753        a1, Operand(a4));
754    __ LoadRoot(a4, Heap::kCatchContextMapRootIndex);
755    __ Check(ne, kDeclarationInCatchContext,
756        a1, Operand(a4));
757  }
758}
759
760
761void FullCodeGenerator::VisitVariableDeclaration(
762    VariableDeclaration* declaration) {
763  // If it was not possible to allocate the variable at compile time, we
764  // need to "declare" it at runtime to make sure it actually exists in the
765  // local context.
766  VariableProxy* proxy = declaration->proxy();
767  VariableMode mode = declaration->mode();
768  Variable* variable = proxy->var();
769  bool hole_init = mode == LET || mode == CONST;
770  switch (variable->location()) {
771    case VariableLocation::GLOBAL:
772    case VariableLocation::UNALLOCATED:
773      DCHECK(!variable->binding_needs_init());
774      globals_->Add(variable->name(), zone());
775      globals_->Add(isolate()->factory()->undefined_value(), zone());
776      break;
777
778    case VariableLocation::PARAMETER:
779    case VariableLocation::LOCAL:
780      if (hole_init) {
781        Comment cmnt(masm_, "[ VariableDeclaration");
782        __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
783        __ sd(a4, StackOperand(variable));
784      }
785      break;
786
787    case VariableLocation::CONTEXT:
788      if (hole_init) {
789        Comment cmnt(masm_, "[ VariableDeclaration");
790        EmitDebugCheckDeclarationContext(variable);
791          __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
792          __ sd(at, ContextMemOperand(cp, variable->index()));
793          // No write barrier since the_hole_value is in old space.
794          PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
795      }
796      break;
797
798    case VariableLocation::LOOKUP: {
799      Comment cmnt(masm_, "[ VariableDeclaration");
800      DCHECK_EQ(VAR, mode);
801      DCHECK(!hole_init);
802      __ li(a2, Operand(variable->name()));
803      __ Push(a2);
804      __ CallRuntime(Runtime::kDeclareEvalVar);
805      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
806      break;
807    }
808  }
809}
810
811
812void FullCodeGenerator::VisitFunctionDeclaration(
813    FunctionDeclaration* declaration) {
814  VariableProxy* proxy = declaration->proxy();
815  Variable* variable = proxy->var();
816  switch (variable->location()) {
817    case VariableLocation::GLOBAL:
818    case VariableLocation::UNALLOCATED: {
819      globals_->Add(variable->name(), zone());
820      Handle<SharedFunctionInfo> function =
821          Compiler::GetSharedFunctionInfo(declaration->fun(), script(), info_);
822      // Check for stack-overflow exception.
823      if (function.is_null()) return SetStackOverflow();
824      globals_->Add(function, zone());
825      break;
826    }
827
828    case VariableLocation::PARAMETER:
829    case VariableLocation::LOCAL: {
830      Comment cmnt(masm_, "[ FunctionDeclaration");
831      VisitForAccumulatorValue(declaration->fun());
832      __ sd(result_register(), StackOperand(variable));
833      break;
834    }
835
836    case VariableLocation::CONTEXT: {
837      Comment cmnt(masm_, "[ FunctionDeclaration");
838      EmitDebugCheckDeclarationContext(variable);
839      VisitForAccumulatorValue(declaration->fun());
840      __ sd(result_register(), ContextMemOperand(cp, variable->index()));
841      int offset = Context::SlotOffset(variable->index());
842      // We know that we have written a function, which is not a smi.
843      __ RecordWriteContextSlot(cp,
844                                offset,
845                                result_register(),
846                                a2,
847                                kRAHasBeenSaved,
848                                kDontSaveFPRegs,
849                                EMIT_REMEMBERED_SET,
850                                OMIT_SMI_CHECK);
851      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
852      break;
853    }
854
855    case VariableLocation::LOOKUP: {
856      Comment cmnt(masm_, "[ FunctionDeclaration");
857      __ li(a2, Operand(variable->name()));
858      PushOperand(a2);
859      // Push initial value for function declaration.
860      VisitForStackValue(declaration->fun());
861      CallRuntimeWithOperands(Runtime::kDeclareEvalFunction);
862      PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
863      break;
864    }
865  }
866}
867
868
869void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
870  // Call the runtime to declare the globals.
871  __ li(a1, Operand(pairs));
872  __ li(a0, Operand(Smi::FromInt(DeclareGlobalsFlags())));
873  __ Push(a1, a0);
874  __ CallRuntime(Runtime::kDeclareGlobals);
875  // Return value is ignored.
876}
877
878
879void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
880  // Call the runtime to declare the modules.
881  __ Push(descriptions);
882  __ CallRuntime(Runtime::kDeclareModules);
883  // Return value is ignored.
884}
885
886
887void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
888  Comment cmnt(masm_, "[ SwitchStatement");
889  Breakable nested_statement(this, stmt);
890  SetStatementPosition(stmt);
891
892  // Keep the switch value on the stack until a case matches.
893  VisitForStackValue(stmt->tag());
894  PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
895
896  ZoneList<CaseClause*>* clauses = stmt->cases();
897  CaseClause* default_clause = NULL;  // Can occur anywhere in the list.
898
899  Label next_test;  // Recycled for each test.
900  // Compile all the tests with branches to their bodies.
901  for (int i = 0; i < clauses->length(); i++) {
902    CaseClause* clause = clauses->at(i);
903    clause->body_target()->Unuse();
904
905    // The default is not a test, but remember it as final fall through.
906    if (clause->is_default()) {
907      default_clause = clause;
908      continue;
909    }
910
911    Comment cmnt(masm_, "[ Case comparison");
912    __ bind(&next_test);
913    next_test.Unuse();
914
915    // Compile the label expression.
916    VisitForAccumulatorValue(clause->label());
917    __ mov(a0, result_register());  // CompareStub requires args in a0, a1.
918
919    // Perform the comparison as if via '==='.
920    __ ld(a1, MemOperand(sp, 0));  // Switch value.
921    bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
922    JumpPatchSite patch_site(masm_);
923    if (inline_smi_code) {
924      Label slow_case;
925      __ or_(a2, a1, a0);
926      patch_site.EmitJumpIfNotSmi(a2, &slow_case);
927
928      __ Branch(&next_test, ne, a1, Operand(a0));
929      __ Drop(1);  // Switch value is no longer needed.
930      __ Branch(clause->body_target());
931
932      __ bind(&slow_case);
933    }
934
935    // Record position before stub call for type feedback.
936    SetExpressionPosition(clause);
937    Handle<Code> ic =
938        CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
939    CallIC(ic, clause->CompareId());
940    patch_site.EmitPatchInfo();
941
942    Label skip;
943    __ Branch(&skip);
944    PrepareForBailout(clause, BailoutState::TOS_REGISTER);
945    __ LoadRoot(at, Heap::kTrueValueRootIndex);
946    __ Branch(&next_test, ne, v0, Operand(at));
947    __ Drop(1);
948    __ Branch(clause->body_target());
949    __ bind(&skip);
950
951    __ Branch(&next_test, ne, v0, Operand(zero_reg));
952    __ Drop(1);  // Switch value is no longer needed.
953    __ Branch(clause->body_target());
954  }
955
956  // Discard the test value and jump to the default if present, otherwise to
957  // the end of the statement.
958  __ bind(&next_test);
959  DropOperands(1);  // Switch value is no longer needed.
960  if (default_clause == NULL) {
961    __ Branch(nested_statement.break_label());
962  } else {
963    __ Branch(default_clause->body_target());
964  }
965
966  // Compile all the case bodies.
967  for (int i = 0; i < clauses->length(); i++) {
968    Comment cmnt(masm_, "[ Case body");
969    CaseClause* clause = clauses->at(i);
970    __ bind(clause->body_target());
971    PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
972    VisitStatements(clause->statements());
973  }
974
975  __ bind(nested_statement.break_label());
976  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
977}
978
979
980void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
981  Comment cmnt(masm_, "[ ForInStatement");
982  SetStatementPosition(stmt, SKIP_BREAK);
983
984  FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
985
986  // Get the object to enumerate over. If the object is null or undefined, skip
987  // over the loop.  See ECMA-262 version 5, section 12.6.4.
988  SetExpressionAsStatementPosition(stmt->enumerable());
989  VisitForAccumulatorValue(stmt->enumerable());
990  __ mov(a0, result_register());
991  OperandStackDepthIncrement(5);
992
993  Label loop, exit;
994  Iteration loop_statement(this, stmt);
995  increment_loop_depth();
996
997  // If the object is null or undefined, skip over the loop, otherwise convert
998  // it to a JS receiver.  See ECMA-262 version 5, section 12.6.4.
999  Label convert, done_convert;
1000  __ JumpIfSmi(a0, &convert);
1001  __ GetObjectType(a0, a1, a1);
1002  __ Branch(USE_DELAY_SLOT, &done_convert, ge, a1,
1003            Operand(FIRST_JS_RECEIVER_TYPE));
1004  __ LoadRoot(at, Heap::kNullValueRootIndex);  // In delay slot.
1005  __ Branch(USE_DELAY_SLOT, &exit, eq, a0, Operand(at));
1006  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);  // In delay slot.
1007  __ Branch(&exit, eq, a0, Operand(at));
1008  __ bind(&convert);
1009  ToObjectStub stub(isolate());
1010  __ CallStub(&stub);
1011  __ mov(a0, v0);
1012  __ bind(&done_convert);
1013  PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
1014  __ push(a0);
1015
1016  // Check cache validity in generated code. If we cannot guarantee cache
1017  // validity, call the runtime system to check cache validity or get the
1018  // property names in a fixed array. Note: Proxies never have an enum cache,
1019  // so will always take the slow path.
1020  Label call_runtime;
1021  __ CheckEnumCache(&call_runtime);
1022
1023  // The enum cache is valid.  Load the map of the object being
1024  // iterated over and use the cache for the iteration.
1025  Label use_cache;
1026  __ ld(v0, FieldMemOperand(a0, HeapObject::kMapOffset));
1027  __ Branch(&use_cache);
1028
1029  // Get the set of properties to enumerate.
1030  __ bind(&call_runtime);
1031  __ push(a0);  // Duplicate the enumerable object on the stack.
1032  __ CallRuntime(Runtime::kForInEnumerate);
1033  PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
1034
1035  // If we got a map from the runtime call, we can do a fast
1036  // modification check. Otherwise, we got a fixed array, and we have
1037  // to do a slow check.
1038  Label fixed_array;
1039  __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
1040  __ LoadRoot(at, Heap::kMetaMapRootIndex);
1041  __ Branch(&fixed_array, ne, a2, Operand(at));
1042
1043  // We got a map in register v0. Get the enumeration cache from it.
1044  Label no_descriptors;
1045  __ bind(&use_cache);
1046
1047  __ EnumLength(a1, v0);
1048  __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0)));
1049
1050  __ LoadInstanceDescriptors(v0, a2);
1051  __ ld(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset));
1052  __ ld(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1053
1054  // Set up the four remaining stack slots.
1055  __ li(a0, Operand(Smi::FromInt(0)));
1056  // Push map, enumeration cache, enumeration cache length (as smi) and zero.
1057  __ Push(v0, a2, a1, a0);
1058  __ jmp(&loop);
1059
1060  __ bind(&no_descriptors);
1061  __ Drop(1);
1062  __ jmp(&exit);
1063
1064  // We got a fixed array in register v0. Iterate through that.
1065  __ bind(&fixed_array);
1066
1067  __ li(a1, Operand(Smi::FromInt(1)));  // Smi(1) indicates slow check
1068  __ Push(a1, v0);  // Smi and array
1069  __ ld(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
1070  __ Push(a1);  // Fixed array length (as smi).
1071  PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
1072  __ li(a0, Operand(Smi::FromInt(0)));
1073  __ Push(a0);  // Initial index.
1074
1075  // Generate code for doing the condition check.
1076  __ bind(&loop);
1077  SetExpressionAsStatementPosition(stmt->each());
1078
1079  // Load the current count to a0, load the length to a1.
1080  __ ld(a0, MemOperand(sp, 0 * kPointerSize));
1081  __ ld(a1, MemOperand(sp, 1 * kPointerSize));
1082  __ Branch(loop_statement.break_label(), hs, a0, Operand(a1));
1083
1084  // Get the current entry of the array into register a3.
1085  __ ld(a2, MemOperand(sp, 2 * kPointerSize));
1086  __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1087  __ SmiScale(a4, a0, kPointerSizeLog2);
1088  __ daddu(a4, a2, a4);  // Array base + scaled (smi) index.
1089  __ ld(a3, MemOperand(a4));  // Current entry.
1090
1091  // Get the expected map from the stack or a smi in the
1092  // permanent slow case into register a2.
1093  __ ld(a2, MemOperand(sp, 3 * kPointerSize));
1094
1095  // Check if the expected map still matches that of the enumerable.
1096  // If not, we may have to filter the key.
1097  Label update_each;
1098  __ ld(a1, MemOperand(sp, 4 * kPointerSize));
1099  __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
1100  __ Branch(&update_each, eq, a4, Operand(a2));
1101
1102  // We need to filter the key, record slow-path here.
1103  int const vector_index = SmiFromSlot(slot)->value();
1104  __ EmitLoadTypeFeedbackVector(a0);
1105  __ li(a2, Operand(TypeFeedbackVector::MegamorphicSentinel(isolate())));
1106  __ sd(a2, FieldMemOperand(a0, FixedArray::OffsetOfElementAt(vector_index)));
1107
1108  // Convert the entry to a string or (smi) 0 if it isn't a property
1109  // any more. If the property has been removed while iterating, we
1110  // just skip it.
1111  __ Push(a1, a3);  // Enumerable and current entry.
1112  __ CallRuntime(Runtime::kForInFilter);
1113  PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
1114  __ mov(a3, result_register());
1115  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1116  __ Branch(loop_statement.continue_label(), eq, a3, Operand(at));
1117
1118  // Update the 'each' property or variable from the possibly filtered
1119  // entry in register a3.
1120  __ bind(&update_each);
1121  __ mov(result_register(), a3);
1122  // Perform the assignment as if via '='.
1123  { EffectContext context(this);
1124    EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
1125    PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
1126  }
1127
1128  // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
1129  PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1130  // Generate code for the body of the loop.
1131  Visit(stmt->body());
1132
1133  // Generate code for the going to the next element by incrementing
1134  // the index (smi) stored on top of the stack.
1135  __ bind(loop_statement.continue_label());
1136  __ pop(a0);
1137  __ Daddu(a0, a0, Operand(Smi::FromInt(1)));
1138  __ push(a0);
1139
1140  EmitBackEdgeBookkeeping(stmt, &loop);
1141  __ Branch(&loop);
1142
1143  // Remove the pointers stored on the stack.
1144  __ bind(loop_statement.break_label());
1145  DropOperands(5);
1146
1147  // Exit and decrement the loop depth.
1148  PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1149  __ bind(&exit);
1150  decrement_loop_depth();
1151}
1152
1153
1154void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
1155                                          FeedbackVectorSlot slot) {
1156  DCHECK(NeedsHomeObject(initializer));
1157  __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1158  __ li(StoreDescriptor::NameRegister(),
1159        Operand(isolate()->factory()->home_object_symbol()));
1160  __ ld(StoreDescriptor::ValueRegister(),
1161        MemOperand(sp, offset * kPointerSize));
1162  EmitLoadStoreICSlot(slot);
1163  CallStoreIC();
1164}
1165
1166
1167void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
1168                                                     int offset,
1169                                                     FeedbackVectorSlot slot) {
1170  DCHECK(NeedsHomeObject(initializer));
1171  __ Move(StoreDescriptor::ReceiverRegister(), v0);
1172  __ li(StoreDescriptor::NameRegister(),
1173        Operand(isolate()->factory()->home_object_symbol()));
1174  __ ld(StoreDescriptor::ValueRegister(),
1175        MemOperand(sp, offset * kPointerSize));
1176  EmitLoadStoreICSlot(slot);
1177  CallStoreIC();
1178}
1179
1180
1181void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
1182                                                      TypeofMode typeof_mode,
1183                                                      Label* slow) {
1184  Register current = cp;
1185  Register next = a1;
1186  Register temp = a2;
1187
1188  Scope* s = scope();
1189  while (s != NULL) {
1190    if (s->num_heap_slots() > 0) {
1191      if (s->calls_sloppy_eval()) {
1192        // Check that extension is "the hole".
1193        __ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
1194        __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1195      }
1196      // Load next context in chain.
1197      __ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
1198      // Walk the rest of the chain without clobbering cp.
1199      current = next;
1200    }
1201    // If no outer scope calls eval, we do not need to check more
1202    // context extensions.
1203    if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1204    s = s->outer_scope();
1205  }
1206
1207  if (s->is_eval_scope()) {
1208    Label loop, fast;
1209    if (!current.is(next)) {
1210      __ Move(next, current);
1211    }
1212    __ bind(&loop);
1213    // Terminate at native context.
1214    __ ld(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1215    __ LoadRoot(a4, Heap::kNativeContextMapRootIndex);
1216    __ Branch(&fast, eq, temp, Operand(a4));
1217    // Check that extension is "the hole".
1218    __ ld(temp, ContextMemOperand(next, Context::EXTENSION_INDEX));
1219    __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1220    // Load next context in chain.
1221    __ ld(next, ContextMemOperand(next, Context::PREVIOUS_INDEX));
1222    __ Branch(&loop);
1223    __ bind(&fast);
1224  }
1225
1226  // All extension objects were empty and it is safe to use a normal global
1227  // load machinery.
1228  EmitGlobalVariableLoad(proxy, typeof_mode);
1229}
1230
1231
1232MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1233                                                                Label* slow) {
1234  DCHECK(var->IsContextSlot());
1235  Register context = cp;
1236  Register next = a3;
1237  Register temp = a4;
1238
1239  for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1240    if (s->num_heap_slots() > 0) {
1241      if (s->calls_sloppy_eval()) {
1242        // Check that extension is "the hole".
1243        __ ld(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1244        __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1245      }
1246      __ ld(next, ContextMemOperand(context, Context::PREVIOUS_INDEX));
1247      // Walk the rest of the chain without clobbering cp.
1248      context = next;
1249    }
1250  }
1251  // Check that last extension is "the hole".
1252  __ ld(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
1253  __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
1254
1255  // This function is used only for loads, not stores, so it's safe to
1256  // return an cp-based operand (the write barrier cannot be allowed to
1257  // destroy the cp register).
1258  return ContextMemOperand(context, var->index());
1259}
1260
1261
1262void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
1263                                                  TypeofMode typeof_mode,
1264                                                  Label* slow, Label* done) {
1265  // Generate fast-case code for variables that might be shadowed by
1266  // eval-introduced variables.  Eval is used a lot without
1267  // introducing variables.  In those cases, we do not want to
1268  // perform a runtime call for all variables in the scope
1269  // containing the eval.
1270  Variable* var = proxy->var();
1271  if (var->mode() == DYNAMIC_GLOBAL) {
1272    EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1273    __ Branch(done);
1274  } else if (var->mode() == DYNAMIC_LOCAL) {
1275    Variable* local = var->local_if_not_shadowed();
1276    __ ld(v0, ContextSlotOperandCheckExtensions(local, slow));
1277    if (local->mode() == LET || local->mode() == CONST) {
1278      __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1279      __ dsubu(at, v0, at);  // Sub as compare: at == 0 on eq.
1280      __ Branch(done, ne, at, Operand(zero_reg));
1281      __ li(a0, Operand(var->name()));
1282      __ push(a0);
1283      __ CallRuntime(Runtime::kThrowReferenceError);
1284    }
1285    __ Branch(done);
1286  }
1287}
1288
1289
1290void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
1291                                               TypeofMode typeof_mode) {
1292#ifdef DEBUG
1293  Variable* var = proxy->var();
1294  DCHECK(var->IsUnallocatedOrGlobalSlot() ||
1295         (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
1296#endif
1297  __ li(LoadGlobalDescriptor::SlotRegister(),
1298        Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
1299  CallLoadGlobalIC(typeof_mode);
1300}
1301
1302
1303void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
1304                                         TypeofMode typeof_mode) {
1305  // Record position before possible IC call.
1306  SetExpressionPosition(proxy);
1307  PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
1308  Variable* var = proxy->var();
1309
1310  // Three cases: global variables, lookup variables, and all other types of
1311  // variables.
1312  switch (var->location()) {
1313    case VariableLocation::GLOBAL:
1314    case VariableLocation::UNALLOCATED: {
1315      Comment cmnt(masm_, "[ Global variable");
1316      EmitGlobalVariableLoad(proxy, typeof_mode);
1317      context()->Plug(v0);
1318      break;
1319    }
1320
1321    case VariableLocation::PARAMETER:
1322    case VariableLocation::LOCAL:
1323    case VariableLocation::CONTEXT: {
1324      DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1325      Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1326                                               : "[ Stack variable");
1327      if (NeedsHoleCheckForLoad(proxy)) {
1328        // Let and const need a read barrier.
1329        GetVar(v0, var);
1330        __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1331        __ dsubu(at, v0, at);  // Sub as compare: at == 0 on eq.
1332        if (var->mode() == LET || var->mode() == CONST) {
1333          // Throw a reference error when using an uninitialized let/const
1334          // binding in harmony mode.
1335          Label done;
1336          __ Branch(&done, ne, at, Operand(zero_reg));
1337          __ li(a0, Operand(var->name()));
1338          __ push(a0);
1339          __ CallRuntime(Runtime::kThrowReferenceError);
1340          __ bind(&done);
1341        }
1342        context()->Plug(v0);
1343        break;
1344      }
1345      context()->Plug(var);
1346      break;
1347    }
1348
1349    case VariableLocation::LOOKUP: {
1350      Comment cmnt(masm_, "[ Lookup variable");
1351      Label done, slow;
1352      // Generate code for loading from variables potentially shadowed
1353      // by eval-introduced variables.
1354      EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done);
1355      __ bind(&slow);
1356      __ Push(var->name());
1357      Runtime::FunctionId function_id =
1358          typeof_mode == NOT_INSIDE_TYPEOF
1359              ? Runtime::kLoadLookupSlot
1360              : Runtime::kLoadLookupSlotInsideTypeof;
1361      __ CallRuntime(function_id);
1362      __ bind(&done);
1363      context()->Plug(v0);
1364    }
1365  }
1366}
1367
1368
1369void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
1370  Expression* expression = (property == NULL) ? NULL : property->value();
1371  if (expression == NULL) {
1372    __ LoadRoot(a1, Heap::kNullValueRootIndex);
1373    PushOperand(a1);
1374  } else {
1375    VisitForStackValue(expression);
1376    if (NeedsHomeObject(expression)) {
1377      DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
1378             property->kind() == ObjectLiteral::Property::SETTER);
1379      int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
1380      EmitSetHomeObject(expression, offset, property->GetSlot());
1381    }
1382  }
1383}
1384
1385
1386void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1387  Comment cmnt(masm_, "[ ObjectLiteral");
1388
1389  Handle<FixedArray> constant_properties = expr->constant_properties();
1390  __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1391  __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
1392  __ li(a1, Operand(constant_properties));
1393  __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
1394  if (MustCreateObjectLiteralWithRuntime(expr)) {
1395    __ Push(a3, a2, a1, a0);
1396    __ CallRuntime(Runtime::kCreateObjectLiteral);
1397  } else {
1398    FastCloneShallowObjectStub stub(isolate(), expr->properties_count());
1399    __ CallStub(&stub);
1400    RestoreContext();
1401  }
1402  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1403
1404  // If result_saved is true the result is on top of the stack.  If
1405  // result_saved is false the result is in v0.
1406  bool result_saved = false;
1407
1408  AccessorTable accessor_table(zone());
1409  int property_index = 0;
1410  for (; property_index < expr->properties()->length(); property_index++) {
1411    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1412    if (property->is_computed_name()) break;
1413    if (property->IsCompileTimeValue()) continue;
1414
1415    Literal* key = property->key()->AsLiteral();
1416    Expression* value = property->value();
1417    if (!result_saved) {
1418      PushOperand(v0);  // Save result on stack.
1419      result_saved = true;
1420    }
1421    switch (property->kind()) {
1422      case ObjectLiteral::Property::CONSTANT:
1423        UNREACHABLE();
1424      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1425        DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1426        // Fall through.
1427      case ObjectLiteral::Property::COMPUTED:
1428        // It is safe to use [[Put]] here because the boilerplate already
1429        // contains computed properties with an uninitialized value.
1430        if (key->value()->IsInternalizedString()) {
1431          if (property->emit_store()) {
1432            VisitForAccumulatorValue(value);
1433            __ mov(StoreDescriptor::ValueRegister(), result_register());
1434            DCHECK(StoreDescriptor::ValueRegister().is(a0));
1435            __ li(StoreDescriptor::NameRegister(), Operand(key->value()));
1436            __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
1437            EmitLoadStoreICSlot(property->GetSlot(0));
1438            CallStoreIC();
1439            PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
1440
1441            if (NeedsHomeObject(value)) {
1442              EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
1443            }
1444          } else {
1445            VisitForEffect(value);
1446          }
1447          break;
1448        }
1449        // Duplicate receiver on stack.
1450        __ ld(a0, MemOperand(sp));
1451        PushOperand(a0);
1452        VisitForStackValue(key);
1453        VisitForStackValue(value);
1454        if (property->emit_store()) {
1455          if (NeedsHomeObject(value)) {
1456            EmitSetHomeObject(value, 2, property->GetSlot());
1457          }
1458          __ li(a0, Operand(Smi::FromInt(SLOPPY)));  // PropertyAttributes.
1459          PushOperand(a0);
1460          CallRuntimeWithOperands(Runtime::kSetProperty);
1461        } else {
1462          DropOperands(3);
1463        }
1464        break;
1465      case ObjectLiteral::Property::PROTOTYPE:
1466        // Duplicate receiver on stack.
1467        __ ld(a0, MemOperand(sp));
1468        PushOperand(a0);
1469        VisitForStackValue(value);
1470        DCHECK(property->emit_store());
1471        CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1472        PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1473                               BailoutState::NO_REGISTERS);
1474        break;
1475      case ObjectLiteral::Property::GETTER:
1476        if (property->emit_store()) {
1477          AccessorTable::Iterator it = accessor_table.lookup(key);
1478          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1479          it->second->getter = property;
1480        }
1481        break;
1482      case ObjectLiteral::Property::SETTER:
1483        if (property->emit_store()) {
1484          AccessorTable::Iterator it = accessor_table.lookup(key);
1485          it->second->bailout_id = expr->GetIdForPropertySet(property_index);
1486          it->second->setter = property;
1487        }
1488        break;
1489    }
1490  }
1491
1492  // Emit code to define accessors, using only a single call to the runtime for
1493  // each pair of corresponding getters and setters.
1494  for (AccessorTable::Iterator it = accessor_table.begin();
1495       it != accessor_table.end();
1496       ++it) {
1497    __ ld(a0, MemOperand(sp));  // Duplicate receiver.
1498    PushOperand(a0);
1499    VisitForStackValue(it->first);
1500    EmitAccessor(it->second->getter);
1501    EmitAccessor(it->second->setter);
1502    __ li(a0, Operand(Smi::FromInt(NONE)));
1503    PushOperand(a0);
1504    CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
1505    PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
1506  }
1507
1508  // Object literals have two parts. The "static" part on the left contains no
1509  // computed property names, and so we can compute its map ahead of time; see
1510  // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part
1511  // starts with the first computed property name, and continues with all
1512  // properties to its right.  All the code from above initializes the static
1513  // component of the object literal, and arranges for the map of the result to
1514  // reflect the static order in which the keys appear. For the dynamic
1515  // properties, we compile them into a series of "SetOwnProperty" runtime
1516  // calls. This will preserve insertion order.
1517  for (; property_index < expr->properties()->length(); property_index++) {
1518    ObjectLiteral::Property* property = expr->properties()->at(property_index);
1519
1520    Expression* value = property->value();
1521    if (!result_saved) {
1522      PushOperand(v0);  // Save result on the stack
1523      result_saved = true;
1524    }
1525
1526    __ ld(a0, MemOperand(sp));  // Duplicate receiver.
1527    PushOperand(a0);
1528
1529    if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1530      DCHECK(!property->is_computed_name());
1531      VisitForStackValue(value);
1532      DCHECK(property->emit_store());
1533      CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
1534      PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1535                             BailoutState::NO_REGISTERS);
1536    } else {
1537      EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
1538      VisitForStackValue(value);
1539      if (NeedsHomeObject(value)) {
1540        EmitSetHomeObject(value, 2, property->GetSlot());
1541      }
1542
1543      switch (property->kind()) {
1544        case ObjectLiteral::Property::CONSTANT:
1545        case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1546        case ObjectLiteral::Property::COMPUTED:
1547          if (property->emit_store()) {
1548            PushOperand(Smi::FromInt(NONE));
1549            PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
1550            CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
1551            PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
1552                                   BailoutState::NO_REGISTERS);
1553          } else {
1554            DropOperands(3);
1555          }
1556          break;
1557
1558        case ObjectLiteral::Property::PROTOTYPE:
1559          UNREACHABLE();
1560          break;
1561
1562        case ObjectLiteral::Property::GETTER:
1563          PushOperand(Smi::FromInt(NONE));
1564          CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
1565          break;
1566
1567        case ObjectLiteral::Property::SETTER:
1568          PushOperand(Smi::FromInt(NONE));
1569          CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
1570          break;
1571      }
1572    }
1573  }
1574
1575  if (result_saved) {
1576    context()->PlugTOS();
1577  } else {
1578    context()->Plug(v0);
1579  }
1580}
1581
1582
1583void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1584  Comment cmnt(masm_, "[ ArrayLiteral");
1585
1586  Handle<FixedArray> constant_elements = expr->constant_elements();
1587  bool has_fast_elements =
1588      IsFastObjectElementsKind(expr->constant_elements_kind());
1589
1590  AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1591  if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1592    // If the only customer of allocation sites is transitioning, then
1593    // we can turn it off if we don't have anywhere else to transition to.
1594    allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1595  }
1596
1597  __ mov(a0, result_register());
1598  __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1599  __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
1600  __ li(a1, Operand(constant_elements));
1601  if (MustCreateArrayLiteralWithRuntime(expr)) {
1602    __ li(a0, Operand(Smi::FromInt(expr->ComputeFlags())));
1603    __ Push(a3, a2, a1, a0);
1604    __ CallRuntime(Runtime::kCreateArrayLiteral);
1605  } else {
1606    FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1607    __ CallStub(&stub);
1608  }
1609  PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
1610
1611  bool result_saved = false;  // Is the result saved to the stack?
1612  ZoneList<Expression*>* subexprs = expr->values();
1613  int length = subexprs->length();
1614
1615  // Emit code to evaluate all the non-constant subexpressions and to store
1616  // them into the newly cloned array.
1617  int array_index = 0;
1618  for (; array_index < length; array_index++) {
1619    Expression* subexpr = subexprs->at(array_index);
1620    DCHECK(!subexpr->IsSpread());
1621
1622    // If the subexpression is a literal or a simple materialized literal it
1623    // is already set in the cloned array.
1624    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1625
1626    if (!result_saved) {
1627      PushOperand(v0);  // array literal
1628      result_saved = true;
1629    }
1630
1631    VisitForAccumulatorValue(subexpr);
1632
1633    __ li(StoreDescriptor::NameRegister(), Operand(Smi::FromInt(array_index)));
1634    __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1635    __ mov(StoreDescriptor::ValueRegister(), result_register());
1636    EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
1637    Handle<Code> ic =
1638        CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
1639    CallIC(ic);
1640
1641    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1642                           BailoutState::NO_REGISTERS);
1643  }
1644
1645  // In case the array literal contains spread expressions it has two parts. The
1646  // first part is  the "static" array which has a literal index is  handled
1647  // above. The second part is the part after the first spread expression
1648  // (inclusive) and these elements gets appended to the array. Note that the
1649  // number elements an iterable produces is unknown ahead of time.
1650  if (array_index < length && result_saved) {
1651    PopOperand(v0);
1652    result_saved = false;
1653  }
1654  for (; array_index < length; array_index++) {
1655    Expression* subexpr = subexprs->at(array_index);
1656
1657    PushOperand(v0);
1658    DCHECK(!subexpr->IsSpread());
1659    VisitForStackValue(subexpr);
1660    CallRuntimeWithOperands(Runtime::kAppendElement);
1661
1662    PrepareForBailoutForId(expr->GetIdForElement(array_index),
1663                           BailoutState::NO_REGISTERS);
1664  }
1665
1666  if (result_saved) {
1667    context()->PlugTOS();
1668  } else {
1669    context()->Plug(v0);
1670  }
1671}
1672
1673
1674void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1675  DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
1676
1677  Comment cmnt(masm_, "[ Assignment");
1678
1679  Property* property = expr->target()->AsProperty();
1680  LhsKind assign_type = Property::GetAssignType(property);
1681
1682  // Evaluate LHS expression.
1683  switch (assign_type) {
1684    case VARIABLE:
1685      // Nothing to do here.
1686      break;
1687    case NAMED_PROPERTY:
1688      if (expr->is_compound()) {
1689        // We need the receiver both on the stack and in the register.
1690        VisitForStackValue(property->obj());
1691        __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
1692      } else {
1693        VisitForStackValue(property->obj());
1694      }
1695      break;
1696    case NAMED_SUPER_PROPERTY:
1697      VisitForStackValue(
1698          property->obj()->AsSuperPropertyReference()->this_var());
1699      VisitForAccumulatorValue(
1700          property->obj()->AsSuperPropertyReference()->home_object());
1701      PushOperand(result_register());
1702      if (expr->is_compound()) {
1703        const Register scratch = a1;
1704        __ ld(scratch, MemOperand(sp, kPointerSize));
1705        PushOperands(scratch, result_register());
1706      }
1707      break;
1708    case KEYED_SUPER_PROPERTY: {
1709      const Register scratch = a1;
1710      VisitForStackValue(
1711          property->obj()->AsSuperPropertyReference()->this_var());
1712      VisitForAccumulatorValue(
1713          property->obj()->AsSuperPropertyReference()->home_object());
1714      __ Move(scratch, result_register());
1715      VisitForAccumulatorValue(property->key());
1716      PushOperands(scratch, result_register());
1717      if (expr->is_compound()) {
1718        const Register scratch1 = a4;
1719        __ ld(scratch1, MemOperand(sp, 2 * kPointerSize));
1720        PushOperands(scratch1, scratch, result_register());
1721      }
1722      break;
1723    }
1724    case KEYED_PROPERTY:
1725      // We need the key and receiver on both the stack and in v0 and a1.
1726      if (expr->is_compound()) {
1727        VisitForStackValue(property->obj());
1728        VisitForStackValue(property->key());
1729        __ ld(LoadDescriptor::ReceiverRegister(),
1730              MemOperand(sp, 1 * kPointerSize));
1731        __ ld(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
1732      } else {
1733        VisitForStackValue(property->obj());
1734        VisitForStackValue(property->key());
1735      }
1736      break;
1737  }
1738
1739  // For compound assignments we need another deoptimization point after the
1740  // variable/property load.
1741  if (expr->is_compound()) {
1742    { AccumulatorValueContext context(this);
1743      switch (assign_type) {
1744        case VARIABLE:
1745          EmitVariableLoad(expr->target()->AsVariableProxy());
1746          PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
1747          break;
1748        case NAMED_PROPERTY:
1749          EmitNamedPropertyLoad(property);
1750          PrepareForBailoutForId(property->LoadId(),
1751                                 BailoutState::TOS_REGISTER);
1752          break;
1753        case NAMED_SUPER_PROPERTY:
1754          EmitNamedSuperPropertyLoad(property);
1755          PrepareForBailoutForId(property->LoadId(),
1756                                 BailoutState::TOS_REGISTER);
1757          break;
1758        case KEYED_SUPER_PROPERTY:
1759          EmitKeyedSuperPropertyLoad(property);
1760          PrepareForBailoutForId(property->LoadId(),
1761                                 BailoutState::TOS_REGISTER);
1762          break;
1763        case KEYED_PROPERTY:
1764          EmitKeyedPropertyLoad(property);
1765          PrepareForBailoutForId(property->LoadId(),
1766                                 BailoutState::TOS_REGISTER);
1767          break;
1768      }
1769    }
1770
1771    Token::Value op = expr->binary_op();
1772    PushOperand(v0);  // Left operand goes on the stack.
1773    VisitForAccumulatorValue(expr->value());
1774
1775    AccumulatorValueContext context(this);
1776    if (ShouldInlineSmiCase(op)) {
1777      EmitInlineSmiBinaryOp(expr->binary_operation(),
1778                            op,
1779                            expr->target(),
1780                            expr->value());
1781    } else {
1782      EmitBinaryOp(expr->binary_operation(), op);
1783    }
1784
1785    // Deoptimization point in case the binary operation may have side effects.
1786    PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
1787  } else {
1788    VisitForAccumulatorValue(expr->value());
1789  }
1790
1791  SetExpressionPosition(expr);
1792
1793  // Store the value.
1794  switch (assign_type) {
1795    case VARIABLE:
1796      EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1797                             expr->op(), expr->AssignmentSlot());
1798      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
1799      context()->Plug(v0);
1800      break;
1801    case NAMED_PROPERTY:
1802      EmitNamedPropertyAssignment(expr);
1803      break;
1804    case NAMED_SUPER_PROPERTY:
1805      EmitNamedSuperPropertyStore(property);
1806      context()->Plug(v0);
1807      break;
1808    case KEYED_SUPER_PROPERTY:
1809      EmitKeyedSuperPropertyStore(property);
1810      context()->Plug(v0);
1811      break;
1812    case KEYED_PROPERTY:
1813      EmitKeyedPropertyAssignment(expr);
1814      break;
1815  }
1816}
1817
1818
1819void FullCodeGenerator::VisitYield(Yield* expr) {
1820  Comment cmnt(masm_, "[ Yield");
1821  SetExpressionPosition(expr);
1822
1823  // Evaluate yielded value first; the initial iterator definition depends on
1824  // this.  It stays on the stack while we update the iterator.
1825  VisitForStackValue(expr->expression());
1826
1827  Label suspend, continuation, post_runtime, resume, exception;
1828
1829  __ jmp(&suspend);
1830  __ bind(&continuation);
1831  // When we arrive here, v0 holds the generator object.
1832  __ RecordGeneratorContinuation();
1833  __ ld(a1, FieldMemOperand(v0, JSGeneratorObject::kResumeModeOffset));
1834  __ ld(v0, FieldMemOperand(v0, JSGeneratorObject::kInputOrDebugPosOffset));
1835  __ Branch(&resume, eq, a1, Operand(Smi::FromInt(JSGeneratorObject::kNext)));
1836  __ Push(result_register());
1837  __ Branch(&exception, eq, a1,
1838            Operand(Smi::FromInt(JSGeneratorObject::kThrow)));
1839  EmitCreateIteratorResult(true);
1840  EmitUnwindAndReturn();
1841
1842  __ bind(&exception);
1843  __ CallRuntime(Runtime::kThrow);
1844
1845  __ bind(&suspend);
1846  OperandStackDepthIncrement(1);  // Not popped on this path.
1847  VisitForAccumulatorValue(expr->generator_object());
1848  DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1849  __ li(a1, Operand(Smi::FromInt(continuation.pos())));
1850  __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset));
1851  __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset));
1852  __ mov(a1, cp);
1853  __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2,
1854                      kRAHasBeenSaved, kDontSaveFPRegs);
1855  __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
1856  __ Branch(&post_runtime, eq, sp, Operand(a1));
1857  __ push(v0);  // generator object
1858  __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1859  RestoreContext();
1860  __ bind(&post_runtime);
1861  PopOperand(result_register());
1862  EmitReturnSequence();
1863
1864  __ bind(&resume);
1865  context()->Plug(result_register());
1866}
1867
1868void FullCodeGenerator::PushOperands(Register reg1, Register reg2) {
1869  OperandStackDepthIncrement(2);
1870  __ Push(reg1, reg2);
1871}
1872
1873void FullCodeGenerator::PushOperands(Register reg1, Register reg2,
1874                                     Register reg3) {
1875  OperandStackDepthIncrement(3);
1876  __ Push(reg1, reg2, reg3);
1877}
1878
1879void FullCodeGenerator::PushOperands(Register reg1, Register reg2,
1880                                     Register reg3, Register reg4) {
1881  OperandStackDepthIncrement(4);
1882  __ Push(reg1, reg2, reg3, reg4);
1883}
1884
1885void FullCodeGenerator::PopOperands(Register reg1, Register reg2) {
1886  OperandStackDepthDecrement(2);
1887  __ Pop(reg1, reg2);
1888}
1889
1890void FullCodeGenerator::EmitOperandStackDepthCheck() {
1891  if (FLAG_debug_code) {
1892    int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp +
1893                        operand_stack_depth_ * kPointerSize;
1894    __ Dsubu(v0, fp, sp);
1895    __ Assert(eq, kUnexpectedStackDepth, v0, Operand(expected_diff));
1896  }
1897}
1898
1899void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
1900  Label allocate, done_allocate;
1901
1902  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &allocate,
1903              NO_ALLOCATION_FLAGS);
1904  __ jmp(&done_allocate);
1905
1906  __ bind(&allocate);
1907  __ Push(Smi::FromInt(JSIteratorResult::kSize));
1908  __ CallRuntime(Runtime::kAllocateInNewSpace);
1909
1910  __ bind(&done_allocate);
1911  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
1912  PopOperand(a2);
1913  __ LoadRoot(a3,
1914              done ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
1915  __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex);
1916  __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
1917  __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset));
1918  __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
1919  __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
1920  __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
1921  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1922}
1923
1924
1925void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
1926                                              Token::Value op,
1927                                              Expression* left_expr,
1928                                              Expression* right_expr) {
1929  Label done, smi_case, stub_call;
1930
1931  Register scratch1 = a2;
1932  Register scratch2 = a3;
1933
1934  // Get the arguments.
1935  Register left = a1;
1936  Register right = a0;
1937  PopOperand(left);
1938  __ mov(a0, result_register());
1939
1940  // Perform combined smi check on both operands.
1941  __ Or(scratch1, left, Operand(right));
1942  STATIC_ASSERT(kSmiTag == 0);
1943  JumpPatchSite patch_site(masm_);
1944  patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1945
1946  __ bind(&stub_call);
1947  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
1948  CallIC(code, expr->BinaryOperationFeedbackId());
1949  patch_site.EmitPatchInfo();
1950  __ jmp(&done);
1951
1952  __ bind(&smi_case);
1953  // Smi case. This code works the same way as the smi-smi case in the type
1954  // recording binary operation stub, see
1955  switch (op) {
1956    case Token::SAR:
1957      __ GetLeastBitsFromSmi(scratch1, right, 5);
1958      __ dsrav(right, left, scratch1);
1959      __ And(v0, right, Operand(0xffffffff00000000L));
1960      break;
1961    case Token::SHL: {
1962      __ SmiUntag(scratch1, left);
1963      __ GetLeastBitsFromSmi(scratch2, right, 5);
1964      __ dsllv(scratch1, scratch1, scratch2);
1965      __ SmiTag(v0, scratch1);
1966      break;
1967    }
1968    case Token::SHR: {
1969      __ SmiUntag(scratch1, left);
1970      __ GetLeastBitsFromSmi(scratch2, right, 5);
1971      __ dsrlv(scratch1, scratch1, scratch2);
1972      __ And(scratch2, scratch1, 0x80000000);
1973      __ Branch(&stub_call, ne, scratch2, Operand(zero_reg));
1974      __ SmiTag(v0, scratch1);
1975      break;
1976    }
1977    case Token::ADD:
1978      __ DaddBranchOvf(v0, left, Operand(right), &stub_call);
1979      break;
1980    case Token::SUB:
1981      __ DsubBranchOvf(v0, left, Operand(right), &stub_call);
1982      break;
1983    case Token::MUL: {
1984      __ Dmulh(v0, left, right);
1985      __ dsra32(scratch2, v0, 0);
1986      __ sra(scratch1, v0, 31);
1987      __ Branch(USE_DELAY_SLOT, &stub_call, ne, scratch2, Operand(scratch1));
1988      __ SmiTag(v0);
1989      __ Branch(USE_DELAY_SLOT, &done, ne, v0, Operand(zero_reg));
1990      __ Daddu(scratch2, right, left);
1991      __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
1992      DCHECK(Smi::FromInt(0) == 0);
1993      __ mov(v0, zero_reg);
1994      break;
1995    }
1996    case Token::BIT_OR:
1997      __ Or(v0, left, Operand(right));
1998      break;
1999    case Token::BIT_AND:
2000      __ And(v0, left, Operand(right));
2001      break;
2002    case Token::BIT_XOR:
2003      __ Xor(v0, left, Operand(right));
2004      break;
2005    default:
2006      UNREACHABLE();
2007  }
2008
2009  __ bind(&done);
2010  context()->Plug(v0);
2011}
2012
2013
2014void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
2015  for (int i = 0; i < lit->properties()->length(); i++) {
2016    ObjectLiteral::Property* property = lit->properties()->at(i);
2017    Expression* value = property->value();
2018
2019    Register scratch = a1;
2020    if (property->is_static()) {
2021      __ ld(scratch, MemOperand(sp, kPointerSize));  // constructor
2022    } else {
2023      __ ld(scratch, MemOperand(sp, 0));  // prototype
2024    }
2025    PushOperand(scratch);
2026    EmitPropertyKey(property, lit->GetIdForProperty(i));
2027
2028    // The static prototype property is read only. We handle the non computed
2029    // property name case in the parser. Since this is the only case where we
2030    // need to check for an own read only property we special case this so we do
2031    // not need to do this for every property.
2032    if (property->is_static() && property->is_computed_name()) {
2033      __ CallRuntime(Runtime::kThrowIfStaticPrototype);
2034      __ push(v0);
2035    }
2036
2037    VisitForStackValue(value);
2038    if (NeedsHomeObject(value)) {
2039      EmitSetHomeObject(value, 2, property->GetSlot());
2040    }
2041
2042    switch (property->kind()) {
2043      case ObjectLiteral::Property::CONSTANT:
2044      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
2045      case ObjectLiteral::Property::PROTOTYPE:
2046        UNREACHABLE();
2047      case ObjectLiteral::Property::COMPUTED:
2048        PushOperand(Smi::FromInt(DONT_ENUM));
2049        PushOperand(Smi::FromInt(property->NeedsSetFunctionName()));
2050        CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral);
2051        break;
2052
2053      case ObjectLiteral::Property::GETTER:
2054        PushOperand(Smi::FromInt(DONT_ENUM));
2055        CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked);
2056        break;
2057
2058      case ObjectLiteral::Property::SETTER:
2059        PushOperand(Smi::FromInt(DONT_ENUM));
2060        CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked);
2061        break;
2062
2063      default:
2064        UNREACHABLE();
2065    }
2066  }
2067}
2068
2069
2070void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
2071  __ mov(a0, result_register());
2072  PopOperand(a1);
2073  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
2074  JumpPatchSite patch_site(masm_);    // unbound, signals no inlined smi code.
2075  CallIC(code, expr->BinaryOperationFeedbackId());
2076  patch_site.EmitPatchInfo();
2077  context()->Plug(v0);
2078}
2079
2080
2081void FullCodeGenerator::EmitAssignment(Expression* expr,
2082                                       FeedbackVectorSlot slot) {
2083  DCHECK(expr->IsValidReferenceExpressionOrThis());
2084
2085  Property* prop = expr->AsProperty();
2086  LhsKind assign_type = Property::GetAssignType(prop);
2087
2088  switch (assign_type) {
2089    case VARIABLE: {
2090      Variable* var = expr->AsVariableProxy()->var();
2091      EffectContext context(this);
2092      EmitVariableAssignment(var, Token::ASSIGN, slot);
2093      break;
2094    }
2095    case NAMED_PROPERTY: {
2096      PushOperand(result_register());  // Preserve value.
2097      VisitForAccumulatorValue(prop->obj());
2098      __ mov(StoreDescriptor::ReceiverRegister(), result_register());
2099      PopOperand(StoreDescriptor::ValueRegister());  // Restore value.
2100      __ li(StoreDescriptor::NameRegister(),
2101            Operand(prop->key()->AsLiteral()->value()));
2102      EmitLoadStoreICSlot(slot);
2103      CallStoreIC();
2104      break;
2105    }
2106    case NAMED_SUPER_PROPERTY: {
2107      PushOperand(v0);
2108      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2109      VisitForAccumulatorValue(
2110          prop->obj()->AsSuperPropertyReference()->home_object());
2111      // stack: value, this; v0: home_object
2112      Register scratch = a2;
2113      Register scratch2 = a3;
2114      __ mov(scratch, result_register());             // home_object
2115      __ ld(v0, MemOperand(sp, kPointerSize));        // value
2116      __ ld(scratch2, MemOperand(sp, 0));             // this
2117      __ sd(scratch2, MemOperand(sp, kPointerSize));  // this
2118      __ sd(scratch, MemOperand(sp, 0));              // home_object
2119      // stack: this, home_object; v0: value
2120      EmitNamedSuperPropertyStore(prop);
2121      break;
2122    }
2123    case KEYED_SUPER_PROPERTY: {
2124      PushOperand(v0);
2125      VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
2126      VisitForStackValue(
2127          prop->obj()->AsSuperPropertyReference()->home_object());
2128      VisitForAccumulatorValue(prop->key());
2129      Register scratch = a2;
2130      Register scratch2 = a3;
2131      __ ld(scratch2, MemOperand(sp, 2 * kPointerSize));  // value
2132      // stack: value, this, home_object; v0: key, a3: value
2133      __ ld(scratch, MemOperand(sp, kPointerSize));  // this
2134      __ sd(scratch, MemOperand(sp, 2 * kPointerSize));
2135      __ ld(scratch, MemOperand(sp, 0));  // home_object
2136      __ sd(scratch, MemOperand(sp, kPointerSize));
2137      __ sd(v0, MemOperand(sp, 0));
2138      __ Move(v0, scratch2);
2139      // stack: this, home_object, key; v0: value.
2140      EmitKeyedSuperPropertyStore(prop);
2141      break;
2142    }
2143    case KEYED_PROPERTY: {
2144      PushOperand(result_register());  // Preserve value.
2145      VisitForStackValue(prop->obj());
2146      VisitForAccumulatorValue(prop->key());
2147      __ Move(StoreDescriptor::NameRegister(), result_register());
2148      PopOperands(StoreDescriptor::ValueRegister(),
2149                  StoreDescriptor::ReceiverRegister());
2150      EmitLoadStoreICSlot(slot);
2151      Handle<Code> ic =
2152          CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2153      CallIC(ic);
2154      break;
2155    }
2156  }
2157  context()->Plug(v0);
2158}
2159
2160
2161void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2162    Variable* var, MemOperand location) {
2163  __ sd(result_register(), location);
2164  if (var->IsContextSlot()) {
2165    // RecordWrite may destroy all its register arguments.
2166    __ Move(a3, result_register());
2167    int offset = Context::SlotOffset(var->index());
2168    __ RecordWriteContextSlot(
2169        a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
2170  }
2171}
2172
2173
2174void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
2175                                               FeedbackVectorSlot slot) {
2176  if (var->IsUnallocated()) {
2177    // Global var, const, or let.
2178    __ mov(StoreDescriptor::ValueRegister(), result_register());
2179    __ li(StoreDescriptor::NameRegister(), Operand(var->name()));
2180    __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
2181    EmitLoadStoreICSlot(slot);
2182    CallStoreIC();
2183
2184  } else if (var->mode() == LET && op != Token::INIT) {
2185    // Non-initializing assignment to let variable needs a write barrier.
2186    DCHECK(!var->IsLookupSlot());
2187    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2188    Label assign;
2189    MemOperand location = VarOperand(var, a1);
2190    __ ld(a3, location);
2191    __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2192    __ Branch(&assign, ne, a3, Operand(a4));
2193    __ li(a3, Operand(var->name()));
2194    __ push(a3);
2195    __ CallRuntime(Runtime::kThrowReferenceError);
2196    // Perform the assignment.
2197    __ bind(&assign);
2198    EmitStoreToStackLocalOrContextSlot(var, location);
2199
2200  } else if (var->mode() == CONST && op != Token::INIT) {
2201    // Assignment to const variable needs a write barrier.
2202    DCHECK(!var->IsLookupSlot());
2203    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2204    Label const_error;
2205    MemOperand location = VarOperand(var, a1);
2206    __ ld(a3, location);
2207    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2208    __ Branch(&const_error, ne, a3, Operand(at));
2209    __ li(a3, Operand(var->name()));
2210    __ push(a3);
2211    __ CallRuntime(Runtime::kThrowReferenceError);
2212    __ bind(&const_error);
2213    __ CallRuntime(Runtime::kThrowConstAssignError);
2214
2215  } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2216    // Initializing assignment to const {this} needs a write barrier.
2217    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2218    Label uninitialized_this;
2219    MemOperand location = VarOperand(var, a1);
2220    __ ld(a3, location);
2221    __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2222    __ Branch(&uninitialized_this, eq, a3, Operand(at));
2223    __ li(a0, Operand(var->name()));
2224    __ Push(a0);
2225    __ CallRuntime(Runtime::kThrowReferenceError);
2226    __ bind(&uninitialized_this);
2227    EmitStoreToStackLocalOrContextSlot(var, location);
2228
2229  } else if (!var->is_const_mode() || op == Token::INIT) {
2230    if (var->IsLookupSlot()) {
2231      __ Push(var->name());
2232      __ Push(v0);
2233      __ CallRuntime(is_strict(language_mode())
2234                         ? Runtime::kStoreLookupSlot_Strict
2235                         : Runtime::kStoreLookupSlot_Sloppy);
2236    } else {
2237      // Assignment to var or initializing assignment to let/const in harmony
2238      // mode.
2239      DCHECK((var->IsStackAllocated() || var->IsContextSlot()));
2240      MemOperand location = VarOperand(var, a1);
2241      if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) {
2242        // Check for an uninitialized let binding.
2243        __ ld(a2, location);
2244        __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2245        __ Check(eq, kLetBindingReInitialization, a2, Operand(a4));
2246      }
2247      EmitStoreToStackLocalOrContextSlot(var, location);
2248    }
2249
2250  } else {
2251    DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT);
2252    if (is_strict(language_mode())) {
2253      __ CallRuntime(Runtime::kThrowConstAssignError);
2254    }
2255    // Silently ignore store in sloppy mode.
2256  }
2257}
2258
2259
2260void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2261  // Assignment to a property, using a named store IC.
2262  Property* prop = expr->target()->AsProperty();
2263  DCHECK(prop != NULL);
2264  DCHECK(prop->key()->IsLiteral());
2265
2266  __ mov(StoreDescriptor::ValueRegister(), result_register());
2267  __ li(StoreDescriptor::NameRegister(),
2268        Operand(prop->key()->AsLiteral()->value()));
2269  PopOperand(StoreDescriptor::ReceiverRegister());
2270  EmitLoadStoreICSlot(expr->AssignmentSlot());
2271  CallStoreIC();
2272
2273  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2274  context()->Plug(v0);
2275}
2276
2277
2278void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) {
2279  // Assignment to named property of super.
2280  // v0 : value
2281  // stack : receiver ('this'), home_object
2282  DCHECK(prop != NULL);
2283  Literal* key = prop->key()->AsLiteral();
2284  DCHECK(key != NULL);
2285
2286  PushOperand(key->value());
2287  PushOperand(v0);
2288  CallRuntimeWithOperands(is_strict(language_mode())
2289                              ? Runtime::kStoreToSuper_Strict
2290                              : Runtime::kStoreToSuper_Sloppy);
2291}
2292
2293
2294void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
2295  // Assignment to named property of super.
2296  // v0 : value
2297  // stack : receiver ('this'), home_object, key
2298  DCHECK(prop != NULL);
2299
2300  PushOperand(v0);
2301  CallRuntimeWithOperands(is_strict(language_mode())
2302                              ? Runtime::kStoreKeyedToSuper_Strict
2303                              : Runtime::kStoreKeyedToSuper_Sloppy);
2304}
2305
2306
2307void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2308  // Assignment to a property, using a keyed store IC.
2309  // Call keyed store IC.
2310  // The arguments are:
2311  // - a0 is the value,
2312  // - a1 is the key,
2313  // - a2 is the receiver.
2314  __ mov(StoreDescriptor::ValueRegister(), result_register());
2315  PopOperands(StoreDescriptor::ReceiverRegister(),
2316              StoreDescriptor::NameRegister());
2317  DCHECK(StoreDescriptor::ValueRegister().is(a0));
2318
2319  Handle<Code> ic =
2320      CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
2321  EmitLoadStoreICSlot(expr->AssignmentSlot());
2322  CallIC(ic);
2323
2324  PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
2325  context()->Plug(v0);
2326}
2327
2328
2329void FullCodeGenerator::CallIC(Handle<Code> code,
2330                               TypeFeedbackId id) {
2331  ic_total_count_++;
2332  __ Call(code, RelocInfo::CODE_TARGET, id);
2333}
2334
2335
2336// Code common for calls using the IC.
2337void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2338  Expression* callee = expr->expression();
2339
2340  // Get the target function.
2341  ConvertReceiverMode convert_mode;
2342  if (callee->IsVariableProxy()) {
2343    { StackValueContext context(this);
2344      EmitVariableLoad(callee->AsVariableProxy());
2345      PrepareForBailout(callee, BailoutState::NO_REGISTERS);
2346    }
2347    // Push undefined as receiver. This is patched in the method prologue if it
2348    // is a sloppy mode method.
2349    __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
2350    PushOperand(at);
2351    convert_mode = ConvertReceiverMode::kNullOrUndefined;
2352  } else {
2353    // Load the function from the receiver.
2354    DCHECK(callee->IsProperty());
2355    DCHECK(!callee->AsProperty()->IsSuperAccess());
2356    __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2357    EmitNamedPropertyLoad(callee->AsProperty());
2358    PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2359                           BailoutState::TOS_REGISTER);
2360    // Push the target function under the receiver.
2361    __ ld(at, MemOperand(sp, 0));
2362    PushOperand(at);
2363    __ sd(v0, MemOperand(sp, kPointerSize));
2364    convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
2365  }
2366
2367  EmitCall(expr, convert_mode);
2368}
2369
2370
2371void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
2372  SetExpressionPosition(expr);
2373  Expression* callee = expr->expression();
2374  DCHECK(callee->IsProperty());
2375  Property* prop = callee->AsProperty();
2376  DCHECK(prop->IsSuperAccess());
2377
2378  Literal* key = prop->key()->AsLiteral();
2379  DCHECK(!key->value()->IsSmi());
2380  // Load the function from the receiver.
2381  const Register scratch = a1;
2382  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2383  VisitForAccumulatorValue(super_ref->home_object());
2384  __ mov(scratch, v0);
2385  VisitForAccumulatorValue(super_ref->this_var());
2386  PushOperands(scratch, v0, v0, scratch);
2387  PushOperand(key->value());
2388
2389  // Stack here:
2390  //  - home_object
2391  //  - this (receiver)
2392  //  - this (receiver) <-- LoadFromSuper will pop here and below.
2393  //  - home_object
2394  //  - key
2395  CallRuntimeWithOperands(Runtime::kLoadFromSuper);
2396  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2397
2398  // Replace home_object with target function.
2399  __ sd(v0, MemOperand(sp, kPointerSize));
2400
2401  // Stack here:
2402  // - target function
2403  // - this (receiver)
2404  EmitCall(expr);
2405}
2406
2407
2408// Code common for calls using the IC.
2409void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2410                                                Expression* key) {
2411  // Load the key.
2412  VisitForAccumulatorValue(key);
2413
2414  Expression* callee = expr->expression();
2415
2416  // Load the function from the receiver.
2417  DCHECK(callee->IsProperty());
2418  __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
2419  __ Move(LoadDescriptor::NameRegister(), v0);
2420  EmitKeyedPropertyLoad(callee->AsProperty());
2421  PrepareForBailoutForId(callee->AsProperty()->LoadId(),
2422                         BailoutState::TOS_REGISTER);
2423
2424  // Push the target function under the receiver.
2425  __ ld(at, MemOperand(sp, 0));
2426  PushOperand(at);
2427  __ sd(v0, MemOperand(sp, kPointerSize));
2428
2429  EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
2430}
2431
2432
2433void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
2434  Expression* callee = expr->expression();
2435  DCHECK(callee->IsProperty());
2436  Property* prop = callee->AsProperty();
2437  DCHECK(prop->IsSuperAccess());
2438
2439  SetExpressionPosition(prop);
2440  // Load the function from the receiver.
2441  const Register scratch = a1;
2442  SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
2443  VisitForAccumulatorValue(super_ref->home_object());
2444  __ Move(scratch, v0);
2445  VisitForAccumulatorValue(super_ref->this_var());
2446  PushOperands(scratch, v0, v0, scratch);
2447  VisitForStackValue(prop->key());
2448
2449  // Stack here:
2450  //  - home_object
2451  //  - this (receiver)
2452  //  - this (receiver) <-- LoadKeyedFromSuper will pop here and below.
2453  //  - home_object
2454  //  - key
2455  CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
2456  PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
2457
2458  // Replace home_object with target function.
2459  __ sd(v0, MemOperand(sp, kPointerSize));
2460
2461  // Stack here:
2462  // - target function
2463  // - this (receiver)
2464  EmitCall(expr);
2465}
2466
2467
2468void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
2469  // Load the arguments.
2470  ZoneList<Expression*>* args = expr->arguments();
2471  int arg_count = args->length();
2472  for (int i = 0; i < arg_count; i++) {
2473    VisitForStackValue(args->at(i));
2474  }
2475
2476  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2477  // Record source position of the IC call.
2478  SetCallPosition(expr, expr->tail_call_mode());
2479  if (expr->tail_call_mode() == TailCallMode::kAllow) {
2480    if (FLAG_trace) {
2481      __ CallRuntime(Runtime::kTraceTailCall);
2482    }
2483    // Update profiling counters before the tail call since we will
2484    // not return to this function.
2485    EmitProfilingCounterHandlingForReturnSequence(true);
2486  }
2487  Handle<Code> ic =
2488      CodeFactory::CallIC(isolate(), arg_count, mode, expr->tail_call_mode())
2489          .code();
2490  __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
2491  __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2492  // Don't assign a type feedback id to the IC, since type feedback is provided
2493  // by the vector above.
2494  CallIC(ic);
2495  OperandStackDepthDecrement(arg_count + 1);
2496
2497  RecordJSReturnSite(expr);
2498  RestoreContext();
2499  context()->DropAndPlug(1, v0);
2500}
2501
2502void FullCodeGenerator::EmitResolvePossiblyDirectEval(Call* expr) {
2503  int arg_count = expr->arguments()->length();
2504  // a6: copy of the first argument or undefined if it doesn't exist.
2505  if (arg_count > 0) {
2506    __ ld(a6, MemOperand(sp, arg_count * kPointerSize));
2507  } else {
2508    __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
2509  }
2510
2511  // a5: the receiver of the enclosing function.
2512  __ ld(a5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2513
2514  // a4: the language mode.
2515  __ li(a4, Operand(Smi::FromInt(language_mode())));
2516
2517  // a1: the start position of the scope the calls resides in.
2518  __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
2519
2520  // a0: the source position of the eval call.
2521  __ li(a0, Operand(Smi::FromInt(expr->position())));
2522
2523  // Do the runtime call.
2524  __ Push(a6, a5, a4, a1, a0);
2525  __ CallRuntime(Runtime::kResolvePossiblyDirectEval);
2526}
2527
2528
2529// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
2530void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
2531  VariableProxy* callee = expr->expression()->AsVariableProxy();
2532  if (callee->var()->IsLookupSlot()) {
2533    Label slow, done;
2534
2535    SetExpressionPosition(callee);
2536    // Generate code for loading from variables potentially shadowed by
2537    // eval-introduced variables.
2538    EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
2539
2540    __ bind(&slow);
2541    // Call the runtime to find the function to call (returned in v0)
2542    // and the object holding it (returned in v1).
2543    __ Push(callee->name());
2544    __ CallRuntime(Runtime::kLoadLookupSlotForCall);
2545    PushOperands(v0, v1);  // Function, receiver.
2546    PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
2547
2548    // If fast case code has been generated, emit code to push the
2549    // function and receiver and have the slow path jump around this
2550    // code.
2551    if (done.is_linked()) {
2552      Label call;
2553      __ Branch(&call);
2554      __ bind(&done);
2555      // Push function.
2556      __ push(v0);
2557      // The receiver is implicitly the global receiver. Indicate this
2558      // by passing the hole to the call function stub.
2559      __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
2560      __ push(a1);
2561      __ bind(&call);
2562    }
2563  } else {
2564    VisitForStackValue(callee);
2565    // refEnv.WithBaseObject()
2566    __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
2567    PushOperand(a2);  // Reserved receiver slot.
2568  }
2569}
2570
2571
2572void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
2573  // In a call to eval, we first call Runtime_ResolvePossiblyDirectEval
2574  // to resolve the function we need to call.  Then we call the resolved
2575  // function using the given arguments.
2576  ZoneList<Expression*>* args = expr->arguments();
2577  int arg_count = args->length();
2578  PushCalleeAndWithBaseObject(expr);
2579
2580  // Push the arguments.
2581  for (int i = 0; i < arg_count; i++) {
2582    VisitForStackValue(args->at(i));
2583  }
2584
2585  // Push a copy of the function (found below the arguments) and
2586  // resolve eval.
2587  __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2588  __ push(a1);
2589  EmitResolvePossiblyDirectEval(expr);
2590
2591  // Touch up the stack with the resolved function.
2592  __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
2593
2594  PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
2595  // Record source position for debugger.
2596  SetCallPosition(expr);
2597  __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2598  __ li(a0, Operand(arg_count));
2599  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny,
2600                                      expr->tail_call_mode()),
2601          RelocInfo::CODE_TARGET);
2602  OperandStackDepthDecrement(arg_count + 1);
2603  RecordJSReturnSite(expr);
2604  RestoreContext();
2605  context()->DropAndPlug(1, v0);
2606}
2607
2608
2609void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2610  Comment cmnt(masm_, "[ CallNew");
2611  // According to ECMA-262, section 11.2.2, page 44, the function
2612  // expression in new calls must be evaluated before the
2613  // arguments.
2614
2615  // Push constructor on the stack.  If it's not a function it's used as
2616  // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2617  // ignored.
2618  DCHECK(!expr->expression()->IsSuperPropertyReference());
2619  VisitForStackValue(expr->expression());
2620
2621  // Push the arguments ("left-to-right") on the stack.
2622  ZoneList<Expression*>* args = expr->arguments();
2623  int arg_count = args->length();
2624  for (int i = 0; i < arg_count; i++) {
2625    VisitForStackValue(args->at(i));
2626  }
2627
2628  // Call the construct call builtin that handles allocation and
2629  // constructor invocation.
2630  SetConstructCallPosition(expr);
2631
2632  // Load function and argument count into a1 and a0.
2633  __ li(a0, Operand(arg_count));
2634  __ ld(a1, MemOperand(sp, arg_count * kPointerSize));
2635
2636  // Record call targets in unoptimized code.
2637  __ EmitLoadTypeFeedbackVector(a2);
2638  __ li(a3, Operand(SmiFromSlot(expr->CallNewFeedbackSlot())));
2639
2640  CallConstructStub stub(isolate());
2641  __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
2642  OperandStackDepthDecrement(arg_count + 1);
2643  PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
2644  RestoreContext();
2645  context()->Plug(v0);
2646}
2647
2648
2649void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
2650  SuperCallReference* super_call_ref =
2651      expr->expression()->AsSuperCallReference();
2652  DCHECK_NOT_NULL(super_call_ref);
2653
2654  // Push the super constructor target on the stack (may be null,
2655  // but the Construct builtin can deal with that properly).
2656  VisitForAccumulatorValue(super_call_ref->this_function_var());
2657  __ AssertFunction(result_register());
2658  __ ld(result_register(),
2659        FieldMemOperand(result_register(), HeapObject::kMapOffset));
2660  __ ld(result_register(),
2661        FieldMemOperand(result_register(), Map::kPrototypeOffset));
2662  PushOperand(result_register());
2663
2664  // Push the arguments ("left-to-right") on the stack.
2665  ZoneList<Expression*>* args = expr->arguments();
2666  int arg_count = args->length();
2667  for (int i = 0; i < arg_count; i++) {
2668    VisitForStackValue(args->at(i));
2669  }
2670
2671  // Call the construct call builtin that handles allocation and
2672  // constructor invocation.
2673  SetConstructCallPosition(expr);
2674
2675  // Load new target into a3.
2676  VisitForAccumulatorValue(super_call_ref->new_target_var());
2677  __ mov(a3, result_register());
2678
2679  // Load function and argument count into a1 and a0.
2680  __ li(a0, Operand(arg_count));
2681  __ ld(a1, MemOperand(sp, arg_count * kPointerSize));
2682
2683  __ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
2684  OperandStackDepthDecrement(arg_count + 1);
2685
2686  RecordJSReturnSite(expr);
2687  RestoreContext();
2688  context()->Plug(v0);
2689}
2690
2691
2692void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2693  ZoneList<Expression*>* args = expr->arguments();
2694  DCHECK(args->length() == 1);
2695
2696  VisitForAccumulatorValue(args->at(0));
2697
2698  Label materialize_true, materialize_false;
2699  Label* if_true = NULL;
2700  Label* if_false = NULL;
2701  Label* fall_through = NULL;
2702  context()->PrepareTest(&materialize_true, &materialize_false,
2703                         &if_true, &if_false, &fall_through);
2704
2705  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2706  __ SmiTst(v0, a4);
2707  Split(eq, a4, Operand(zero_reg), if_true, if_false, fall_through);
2708
2709  context()->Plug(if_true, if_false);
2710}
2711
2712
2713void FullCodeGenerator::EmitIsJSReceiver(CallRuntime* expr) {
2714  ZoneList<Expression*>* args = expr->arguments();
2715  DCHECK(args->length() == 1);
2716
2717  VisitForAccumulatorValue(args->at(0));
2718
2719  Label materialize_true, materialize_false;
2720  Label* if_true = NULL;
2721  Label* if_false = NULL;
2722  Label* fall_through = NULL;
2723  context()->PrepareTest(&materialize_true, &materialize_false,
2724                         &if_true, &if_false, &fall_through);
2725
2726  __ JumpIfSmi(v0, if_false);
2727  __ GetObjectType(v0, a1, a1);
2728  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2729  Split(ge, a1, Operand(FIRST_JS_RECEIVER_TYPE),
2730        if_true, if_false, fall_through);
2731
2732  context()->Plug(if_true, if_false);
2733}
2734
2735
2736void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2737  ZoneList<Expression*>* args = expr->arguments();
2738  DCHECK(args->length() == 1);
2739
2740  VisitForAccumulatorValue(args->at(0));
2741
2742  Label materialize_true, materialize_false;
2743  Label* if_true = NULL;
2744  Label* if_false = NULL;
2745  Label* fall_through = NULL;
2746  context()->PrepareTest(&materialize_true, &materialize_false,
2747                         &if_true, &if_false, &fall_through);
2748
2749  __ JumpIfSmi(v0, if_false);
2750  __ GetObjectType(v0, a1, a1);
2751  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2752  Split(eq, a1, Operand(JS_ARRAY_TYPE),
2753        if_true, if_false, fall_through);
2754
2755  context()->Plug(if_true, if_false);
2756}
2757
2758
2759void FullCodeGenerator::EmitIsTypedArray(CallRuntime* expr) {
2760  ZoneList<Expression*>* args = expr->arguments();
2761  DCHECK(args->length() == 1);
2762
2763  VisitForAccumulatorValue(args->at(0));
2764
2765  Label materialize_true, materialize_false;
2766  Label* if_true = NULL;
2767  Label* if_false = NULL;
2768  Label* fall_through = NULL;
2769  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2770                         &if_false, &fall_through);
2771
2772  __ JumpIfSmi(v0, if_false);
2773  __ GetObjectType(v0, a1, a1);
2774  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2775  Split(eq, a1, Operand(JS_TYPED_ARRAY_TYPE), if_true, if_false, fall_through);
2776
2777  context()->Plug(if_true, if_false);
2778}
2779
2780
2781void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2782  ZoneList<Expression*>* args = expr->arguments();
2783  DCHECK(args->length() == 1);
2784
2785  VisitForAccumulatorValue(args->at(0));
2786
2787  Label materialize_true, materialize_false;
2788  Label* if_true = NULL;
2789  Label* if_false = NULL;
2790  Label* fall_through = NULL;
2791  context()->PrepareTest(&materialize_true, &materialize_false,
2792                         &if_true, &if_false, &fall_through);
2793
2794  __ JumpIfSmi(v0, if_false);
2795  __ GetObjectType(v0, a1, a1);
2796  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2797  Split(eq, a1, Operand(JS_REGEXP_TYPE), if_true, if_false, fall_through);
2798
2799  context()->Plug(if_true, if_false);
2800}
2801
2802
2803void FullCodeGenerator::EmitIsJSProxy(CallRuntime* expr) {
2804  ZoneList<Expression*>* args = expr->arguments();
2805  DCHECK(args->length() == 1);
2806
2807  VisitForAccumulatorValue(args->at(0));
2808
2809  Label materialize_true, materialize_false;
2810  Label* if_true = NULL;
2811  Label* if_false = NULL;
2812  Label* fall_through = NULL;
2813  context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
2814                         &if_false, &fall_through);
2815
2816  __ JumpIfSmi(v0, if_false);
2817  __ GetObjectType(v0, a1, a1);
2818  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2819  Split(eq, a1, Operand(JS_PROXY_TYPE), if_true, if_false, fall_through);
2820
2821  context()->Plug(if_true, if_false);
2822}
2823
2824
2825void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2826  ZoneList<Expression*>* args = expr->arguments();
2827  DCHECK(args->length() == 1);
2828  Label done, null, function, non_function_constructor;
2829
2830  VisitForAccumulatorValue(args->at(0));
2831
2832  // If the object is not a JSReceiver, we return null.
2833  __ JumpIfSmi(v0, &null);
2834  STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
2835  __ GetObjectType(v0, v0, a1);  // Map is now in v0.
2836  __ Branch(&null, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
2837
2838  // Return 'Function' for JSFunction and JSBoundFunction objects.
2839  STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
2840  __ Branch(&function, hs, a1, Operand(FIRST_FUNCTION_TYPE));
2841
2842  // Check if the constructor in the map is a JS function.
2843  Register instance_type = a2;
2844  __ GetMapConstructor(v0, v0, a1, instance_type);
2845  __ Branch(&non_function_constructor, ne, instance_type,
2846            Operand(JS_FUNCTION_TYPE));
2847
2848  // v0 now contains the constructor function. Grab the
2849  // instance class name from there.
2850  __ ld(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
2851  __ ld(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset));
2852  __ Branch(&done);
2853
2854  // Functions have class 'Function'.
2855  __ bind(&function);
2856  __ LoadRoot(v0, Heap::kFunction_stringRootIndex);
2857  __ jmp(&done);
2858
2859  // Objects with a non-function constructor have class 'Object'.
2860  __ bind(&non_function_constructor);
2861  __ LoadRoot(v0, Heap::kObject_stringRootIndex);
2862  __ jmp(&done);
2863
2864  // Non-JS objects have class null.
2865  __ bind(&null);
2866  __ LoadRoot(v0, Heap::kNullValueRootIndex);
2867
2868  // All done.
2869  __ bind(&done);
2870
2871  context()->Plug(v0);
2872}
2873
2874
2875void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
2876  ZoneList<Expression*>* args = expr->arguments();
2877  DCHECK(args->length() == 1);
2878
2879  VisitForAccumulatorValue(args->at(0));  // Load the object.
2880
2881  Label done;
2882  // If the object is a smi return the object.
2883  __ JumpIfSmi(v0, &done);
2884  // If the object is not a value type, return the object.
2885  __ GetObjectType(v0, a1, a1);
2886  __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE));
2887
2888  __ ld(v0, FieldMemOperand(v0, JSValue::kValueOffset));
2889
2890  __ bind(&done);
2891  context()->Plug(v0);
2892}
2893
2894
2895void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
2896  ZoneList<Expression*>* args = expr->arguments();
2897  DCHECK(args->length() == 1);
2898
2899  VisitForAccumulatorValue(args->at(0));
2900
2901  Label done;
2902  StringCharFromCodeGenerator generator(v0, a1);
2903  generator.GenerateFast(masm_);
2904  __ jmp(&done);
2905
2906  NopRuntimeCallHelper call_helper;
2907  generator.GenerateSlow(masm_, call_helper);
2908
2909  __ bind(&done);
2910  context()->Plug(a1);
2911}
2912
2913
2914void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
2915  ZoneList<Expression*>* args = expr->arguments();
2916  DCHECK(args->length() == 2);
2917
2918  VisitForStackValue(args->at(0));
2919  VisitForAccumulatorValue(args->at(1));
2920  __ mov(a0, result_register());
2921
2922  Register object = a1;
2923  Register index = a0;
2924  Register result = v0;
2925
2926  PopOperand(object);
2927
2928  Label need_conversion;
2929  Label index_out_of_range;
2930  Label done;
2931  StringCharCodeAtGenerator generator(object, index, result, &need_conversion,
2932                                      &need_conversion, &index_out_of_range);
2933  generator.GenerateFast(masm_);
2934  __ jmp(&done);
2935
2936  __ bind(&index_out_of_range);
2937  // When the index is out of range, the spec requires us to return
2938  // NaN.
2939  __ LoadRoot(result, Heap::kNanValueRootIndex);
2940  __ jmp(&done);
2941
2942  __ bind(&need_conversion);
2943  // Load the undefined value into the result register, which will
2944  // trigger conversion.
2945  __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2946  __ jmp(&done);
2947
2948  NopRuntimeCallHelper call_helper;
2949  generator.GenerateSlow(masm_, NOT_PART_OF_IC_HANDLER, call_helper);
2950
2951  __ bind(&done);
2952  context()->Plug(result);
2953}
2954
2955
2956void FullCodeGenerator::EmitCall(CallRuntime* expr) {
2957  ZoneList<Expression*>* args = expr->arguments();
2958  DCHECK_LE(2, args->length());
2959  // Push target, receiver and arguments onto the stack.
2960  for (Expression* const arg : *args) {
2961    VisitForStackValue(arg);
2962  }
2963  PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
2964  // Move target to a1.
2965  int const argc = args->length() - 2;
2966  __ ld(a1, MemOperand(sp, (argc + 1) * kPointerSize));
2967  // Call the target.
2968  __ li(a0, Operand(argc));
2969  __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
2970  OperandStackDepthDecrement(argc + 1);
2971  RestoreContext();
2972  // Discard the function left on TOS.
2973  context()->DropAndPlug(1, v0);
2974}
2975
2976
2977void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
2978  ZoneList<Expression*>* args = expr->arguments();
2979  VisitForAccumulatorValue(args->at(0));
2980
2981  Label materialize_true, materialize_false;
2982  Label* if_true = NULL;
2983  Label* if_false = NULL;
2984  Label* fall_through = NULL;
2985  context()->PrepareTest(&materialize_true, &materialize_false,
2986                         &if_true, &if_false, &fall_through);
2987
2988  __ lwu(a0, FieldMemOperand(v0, String::kHashFieldOffset));
2989  __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
2990
2991  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2992  Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
2993
2994  context()->Plug(if_true, if_false);
2995}
2996
2997
2998void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
2999  ZoneList<Expression*>* args = expr->arguments();
3000  DCHECK(args->length() == 1);
3001  VisitForAccumulatorValue(args->at(0));
3002
3003  __ AssertString(v0);
3004
3005  __ lwu(v0, FieldMemOperand(v0, String::kHashFieldOffset));
3006  __ IndexFromHash(v0, v0);
3007
3008  context()->Plug(v0);
3009}
3010
3011
3012void FullCodeGenerator::EmitGetSuperConstructor(CallRuntime* expr) {
3013  ZoneList<Expression*>* args = expr->arguments();
3014  DCHECK_EQ(1, args->length());
3015  VisitForAccumulatorValue(args->at(0));
3016  __ AssertFunction(v0);
3017  __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
3018  __ ld(v0, FieldMemOperand(v0, Map::kPrototypeOffset));
3019  context()->Plug(v0);
3020}
3021
3022void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
3023  DCHECK(expr->arguments()->length() == 0);
3024  ExternalReference debug_is_active =
3025      ExternalReference::debug_is_active_address(isolate());
3026  __ li(at, Operand(debug_is_active));
3027  __ lbu(v0, MemOperand(at));
3028  __ SmiTag(v0);
3029  context()->Plug(v0);
3030}
3031
3032
3033void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
3034  ZoneList<Expression*>* args = expr->arguments();
3035  DCHECK_EQ(2, args->length());
3036  VisitForStackValue(args->at(0));
3037  VisitForStackValue(args->at(1));
3038
3039  Label runtime, done;
3040
3041  __ Allocate(JSIteratorResult::kSize, v0, a2, a3, &runtime,
3042              NO_ALLOCATION_FLAGS);
3043  __ LoadNativeContextSlot(Context::ITERATOR_RESULT_MAP_INDEX, a1);
3044  __ Pop(a2, a3);
3045  __ LoadRoot(a4, Heap::kEmptyFixedArrayRootIndex);
3046  __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
3047  __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset));
3048  __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
3049  __ sd(a2, FieldMemOperand(v0, JSIteratorResult::kValueOffset));
3050  __ sd(a3, FieldMemOperand(v0, JSIteratorResult::kDoneOffset));
3051  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
3052  __ jmp(&done);
3053
3054  __ bind(&runtime);
3055  CallRuntimeWithOperands(Runtime::kCreateIterResultObject);
3056
3057  __ bind(&done);
3058  context()->Plug(v0);
3059}
3060
3061
3062void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
3063  // Push function.
3064  __ LoadNativeContextSlot(expr->context_index(), v0);
3065  PushOperand(v0);
3066
3067  // Push undefined as the receiver.
3068  __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
3069  PushOperand(v0);
3070}
3071
3072
3073void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
3074  ZoneList<Expression*>* args = expr->arguments();
3075  int arg_count = args->length();
3076
3077  SetCallPosition(expr);
3078  __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
3079  __ li(a0, Operand(arg_count));
3080  __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
3081          RelocInfo::CODE_TARGET);
3082  OperandStackDepthDecrement(arg_count + 1);
3083  RestoreContext();
3084}
3085
3086
3087void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3088  switch (expr->op()) {
3089    case Token::DELETE: {
3090      Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3091      Property* property = expr->expression()->AsProperty();
3092      VariableProxy* proxy = expr->expression()->AsVariableProxy();
3093
3094      if (property != NULL) {
3095        VisitForStackValue(property->obj());
3096        VisitForStackValue(property->key());
3097        CallRuntimeWithOperands(is_strict(language_mode())
3098                                    ? Runtime::kDeleteProperty_Strict
3099                                    : Runtime::kDeleteProperty_Sloppy);
3100        context()->Plug(v0);
3101      } else if (proxy != NULL) {
3102        Variable* var = proxy->var();
3103        // Delete of an unqualified identifier is disallowed in strict mode but
3104        // "delete this" is allowed.
3105        bool is_this = var->HasThisName(isolate());
3106        DCHECK(is_sloppy(language_mode()) || is_this);
3107        if (var->IsUnallocatedOrGlobalSlot()) {
3108          __ LoadGlobalObject(a2);
3109          __ li(a1, Operand(var->name()));
3110          __ Push(a2, a1);
3111          __ CallRuntime(Runtime::kDeleteProperty_Sloppy);
3112          context()->Plug(v0);
3113        } else if (var->IsStackAllocated() || var->IsContextSlot()) {
3114          // Result of deleting non-global, non-dynamic variables is false.
3115          // The subexpression does not have side effects.
3116          context()->Plug(is_this);
3117        } else {
3118          // Non-global variable.  Call the runtime to try to delete from the
3119          // context where the variable was introduced.
3120          DCHECK(!context_register().is(a2));
3121          __ Push(var->name());
3122          __ CallRuntime(Runtime::kDeleteLookupSlot);
3123          context()->Plug(v0);
3124        }
3125      } else {
3126        // Result of deleting non-property, non-variable reference is true.
3127        // The subexpression may have side effects.
3128        VisitForEffect(expr->expression());
3129        context()->Plug(true);
3130      }
3131      break;
3132    }
3133
3134    case Token::VOID: {
3135      Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3136      VisitForEffect(expr->expression());
3137      context()->Plug(Heap::kUndefinedValueRootIndex);
3138      break;
3139    }
3140
3141    case Token::NOT: {
3142      Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3143      if (context()->IsEffect()) {
3144        // Unary NOT has no side effects so it's only necessary to visit the
3145        // subexpression.  Match the optimizing compiler by not branching.
3146        VisitForEffect(expr->expression());
3147      } else if (context()->IsTest()) {
3148        const TestContext* test = TestContext::cast(context());
3149        // The labels are swapped for the recursive call.
3150        VisitForControl(expr->expression(),
3151                        test->false_label(),
3152                        test->true_label(),
3153                        test->fall_through());
3154        context()->Plug(test->true_label(), test->false_label());
3155      } else {
3156        // We handle value contexts explicitly rather than simply visiting
3157        // for control and plugging the control flow into the context,
3158        // because we need to prepare a pair of extra administrative AST ids
3159        // for the optimizing compiler.
3160        DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
3161        Label materialize_true, materialize_false, done;
3162        VisitForControl(expr->expression(),
3163                        &materialize_false,
3164                        &materialize_true,
3165                        &materialize_true);
3166        if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
3167        __ bind(&materialize_true);
3168        PrepareForBailoutForId(expr->MaterializeTrueId(),
3169                               BailoutState::NO_REGISTERS);
3170        __ LoadRoot(v0, Heap::kTrueValueRootIndex);
3171        if (context()->IsStackValue()) __ push(v0);
3172        __ jmp(&done);
3173        __ bind(&materialize_false);
3174        PrepareForBailoutForId(expr->MaterializeFalseId(),
3175                               BailoutState::NO_REGISTERS);
3176        __ LoadRoot(v0, Heap::kFalseValueRootIndex);
3177        if (context()->IsStackValue()) __ push(v0);
3178        __ bind(&done);
3179      }
3180      break;
3181    }
3182
3183    case Token::TYPEOF: {
3184      Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3185      {
3186        AccumulatorValueContext context(this);
3187        VisitForTypeofValue(expr->expression());
3188      }
3189      __ mov(a3, v0);
3190      TypeofStub typeof_stub(isolate());
3191      __ CallStub(&typeof_stub);
3192      context()->Plug(v0);
3193      break;
3194    }
3195
3196    default:
3197      UNREACHABLE();
3198  }
3199}
3200
3201
3202void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
3203  DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
3204
3205  Comment cmnt(masm_, "[ CountOperation");
3206
3207  Property* prop = expr->expression()->AsProperty();
3208  LhsKind assign_type = Property::GetAssignType(prop);
3209
3210  // Evaluate expression and get value.
3211  if (assign_type == VARIABLE) {
3212    DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
3213    AccumulatorValueContext context(this);
3214    EmitVariableLoad(expr->expression()->AsVariableProxy());
3215  } else {
3216    // Reserve space for result of postfix operation.
3217    if (expr->is_postfix() && !context()->IsEffect()) {
3218      __ li(at, Operand(Smi::FromInt(0)));
3219      PushOperand(at);
3220    }
3221    switch (assign_type) {
3222      case NAMED_PROPERTY: {
3223        // Put the object both on the stack and in the register.
3224        VisitForStackValue(prop->obj());
3225        __ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
3226        EmitNamedPropertyLoad(prop);
3227        break;
3228      }
3229
3230      case NAMED_SUPER_PROPERTY: {
3231        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3232        VisitForAccumulatorValue(
3233            prop->obj()->AsSuperPropertyReference()->home_object());
3234        PushOperand(result_register());
3235        const Register scratch = a1;
3236        __ ld(scratch, MemOperand(sp, kPointerSize));
3237        PushOperands(scratch, result_register());
3238        EmitNamedSuperPropertyLoad(prop);
3239        break;
3240      }
3241
3242      case KEYED_SUPER_PROPERTY: {
3243        VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var());
3244        VisitForAccumulatorValue(
3245            prop->obj()->AsSuperPropertyReference()->home_object());
3246        const Register scratch = a1;
3247        const Register scratch1 = a4;
3248        __ Move(scratch, result_register());
3249        VisitForAccumulatorValue(prop->key());
3250        PushOperands(scratch, result_register());
3251        __ ld(scratch1, MemOperand(sp, 2 * kPointerSize));
3252        PushOperands(scratch1, scratch, result_register());
3253        EmitKeyedSuperPropertyLoad(prop);
3254        break;
3255      }
3256
3257      case KEYED_PROPERTY: {
3258        VisitForStackValue(prop->obj());
3259        VisitForStackValue(prop->key());
3260        __ ld(LoadDescriptor::ReceiverRegister(),
3261              MemOperand(sp, 1 * kPointerSize));
3262        __ ld(LoadDescriptor::NameRegister(), MemOperand(sp, 0));
3263        EmitKeyedPropertyLoad(prop);
3264        break;
3265      }
3266
3267      case VARIABLE:
3268        UNREACHABLE();
3269    }
3270  }
3271
3272  // We need a second deoptimization point after loading the value
3273  // in case evaluating the property load my have a side effect.
3274  if (assign_type == VARIABLE) {
3275    PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
3276  } else {
3277    PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
3278  }
3279
3280  // Inline smi case if we are in a loop.
3281  Label stub_call, done;
3282  JumpPatchSite patch_site(masm_);
3283
3284  int count_value = expr->op() == Token::INC ? 1 : -1;
3285  __ mov(a0, v0);
3286  if (ShouldInlineSmiCase(expr->op())) {
3287    Label slow;
3288    patch_site.EmitJumpIfNotSmi(v0, &slow);
3289
3290    // Save result for postfix expressions.
3291    if (expr->is_postfix()) {
3292      if (!context()->IsEffect()) {
3293        // Save the result on the stack. If we have a named or keyed property
3294        // we store the result under the receiver that is currently on top
3295        // of the stack.
3296        switch (assign_type) {
3297          case VARIABLE:
3298            __ push(v0);
3299            break;
3300          case NAMED_PROPERTY:
3301            __ sd(v0, MemOperand(sp, kPointerSize));
3302            break;
3303          case NAMED_SUPER_PROPERTY:
3304            __ sd(v0, MemOperand(sp, 2 * kPointerSize));
3305            break;
3306          case KEYED_PROPERTY:
3307            __ sd(v0, MemOperand(sp, 2 * kPointerSize));
3308            break;
3309          case KEYED_SUPER_PROPERTY:
3310            __ sd(v0, MemOperand(sp, 3 * kPointerSize));
3311            break;
3312        }
3313      }
3314    }
3315
3316    Register scratch1 = a1;
3317    __ li(scratch1, Operand(Smi::FromInt(count_value)));
3318    __ DaddBranchNoOvf(v0, v0, Operand(scratch1), &done);
3319    // Call stub. Undo operation first.
3320    __ Move(v0, a0);
3321    __ jmp(&stub_call);
3322    __ bind(&slow);
3323  }
3324
3325  // Convert old value into a number.
3326  __ Call(isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET);
3327  PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
3328
3329  // Save result for postfix expressions.
3330  if (expr->is_postfix()) {
3331    if (!context()->IsEffect()) {
3332      // Save the result on the stack. If we have a named or keyed property
3333      // we store the result under the receiver that is currently on top
3334      // of the stack.
3335      switch (assign_type) {
3336        case VARIABLE:
3337          PushOperand(v0);
3338          break;
3339        case NAMED_PROPERTY:
3340          __ sd(v0, MemOperand(sp, kPointerSize));
3341          break;
3342        case NAMED_SUPER_PROPERTY:
3343          __ sd(v0, MemOperand(sp, 2 * kPointerSize));
3344          break;
3345        case KEYED_PROPERTY:
3346          __ sd(v0, MemOperand(sp, 2 * kPointerSize));
3347          break;
3348        case KEYED_SUPER_PROPERTY:
3349          __ sd(v0, MemOperand(sp, 3 * kPointerSize));
3350          break;
3351      }
3352    }
3353  }
3354
3355  __ bind(&stub_call);
3356  __ mov(a1, v0);
3357  __ li(a0, Operand(Smi::FromInt(count_value)));
3358
3359  SetExpressionPosition(expr);
3360
3361  Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
3362  CallIC(code, expr->CountBinOpFeedbackId());
3363  patch_site.EmitPatchInfo();
3364  __ bind(&done);
3365
3366  // Store the value returned in v0.
3367  switch (assign_type) {
3368    case VARIABLE:
3369      if (expr->is_postfix()) {
3370        { EffectContext context(this);
3371          EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3372                                 Token::ASSIGN, expr->CountSlot());
3373          PrepareForBailoutForId(expr->AssignmentId(),
3374                                 BailoutState::TOS_REGISTER);
3375          context.Plug(v0);
3376        }
3377        // For all contexts except EffectConstant we have the result on
3378        // top of the stack.
3379        if (!context()->IsEffect()) {
3380          context()->PlugTOS();
3381        }
3382      } else {
3383        EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3384                               Token::ASSIGN, expr->CountSlot());
3385        PrepareForBailoutForId(expr->AssignmentId(),
3386                               BailoutState::TOS_REGISTER);
3387        context()->Plug(v0);
3388      }
3389      break;
3390    case NAMED_PROPERTY: {
3391      __ mov(StoreDescriptor::ValueRegister(), result_register());
3392      __ li(StoreDescriptor::NameRegister(),
3393            Operand(prop->key()->AsLiteral()->value()));
3394      PopOperand(StoreDescriptor::ReceiverRegister());
3395      EmitLoadStoreICSlot(expr->CountSlot());
3396      CallStoreIC();
3397      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3398      if (expr->is_postfix()) {
3399        if (!context()->IsEffect()) {
3400          context()->PlugTOS();
3401        }
3402      } else {
3403        context()->Plug(v0);
3404      }
3405      break;
3406    }
3407    case NAMED_SUPER_PROPERTY: {
3408      EmitNamedSuperPropertyStore(prop);
3409      if (expr->is_postfix()) {
3410        if (!context()->IsEffect()) {
3411          context()->PlugTOS();
3412        }
3413      } else {
3414        context()->Plug(v0);
3415      }
3416      break;
3417    }
3418    case KEYED_SUPER_PROPERTY: {
3419      EmitKeyedSuperPropertyStore(prop);
3420      if (expr->is_postfix()) {
3421        if (!context()->IsEffect()) {
3422          context()->PlugTOS();
3423        }
3424      } else {
3425        context()->Plug(v0);
3426      }
3427      break;
3428    }
3429    case KEYED_PROPERTY: {
3430      __ mov(StoreDescriptor::ValueRegister(), result_register());
3431      PopOperands(StoreDescriptor::ReceiverRegister(),
3432                  StoreDescriptor::NameRegister());
3433      Handle<Code> ic =
3434          CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
3435      EmitLoadStoreICSlot(expr->CountSlot());
3436      CallIC(ic);
3437      PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
3438      if (expr->is_postfix()) {
3439        if (!context()->IsEffect()) {
3440          context()->PlugTOS();
3441        }
3442      } else {
3443        context()->Plug(v0);
3444      }
3445      break;
3446    }
3447  }
3448}
3449
3450
3451void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
3452                                                 Expression* sub_expr,
3453                                                 Handle<String> check) {
3454  Label materialize_true, materialize_false;
3455  Label* if_true = NULL;
3456  Label* if_false = NULL;
3457  Label* fall_through = NULL;
3458  context()->PrepareTest(&materialize_true, &materialize_false,
3459                         &if_true, &if_false, &fall_through);
3460
3461  { AccumulatorValueContext context(this);
3462    VisitForTypeofValue(sub_expr);
3463  }
3464  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3465
3466  Factory* factory = isolate()->factory();
3467  if (String::Equals(check, factory->number_string())) {
3468    __ JumpIfSmi(v0, if_true);
3469    __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
3470    __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3471    Split(eq, v0, Operand(at), if_true, if_false, fall_through);
3472  } else if (String::Equals(check, factory->string_string())) {
3473    __ JumpIfSmi(v0, if_false);
3474    __ GetObjectType(v0, v0, a1);
3475    Split(lt, a1, Operand(FIRST_NONSTRING_TYPE), if_true, if_false,
3476          fall_through);
3477  } else if (String::Equals(check, factory->symbol_string())) {
3478    __ JumpIfSmi(v0, if_false);
3479    __ GetObjectType(v0, v0, a1);
3480    Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
3481  } else if (String::Equals(check, factory->boolean_string())) {
3482    __ LoadRoot(at, Heap::kTrueValueRootIndex);
3483    __ Branch(if_true, eq, v0, Operand(at));
3484    __ LoadRoot(at, Heap::kFalseValueRootIndex);
3485    Split(eq, v0, Operand(at), if_true, if_false, fall_through);
3486  } else if (String::Equals(check, factory->undefined_string())) {
3487    __ LoadRoot(at, Heap::kNullValueRootIndex);
3488    __ Branch(if_false, eq, v0, Operand(at));
3489    __ JumpIfSmi(v0, if_false);
3490    // Check for undetectable objects => true.
3491    __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
3492    __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
3493    __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
3494    Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
3495  } else if (String::Equals(check, factory->function_string())) {
3496    __ JumpIfSmi(v0, if_false);
3497    __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
3498    __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
3499    __ And(a1, a1,
3500           Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3501    Split(eq, a1, Operand(1 << Map::kIsCallable), if_true, if_false,
3502          fall_through);
3503  } else if (String::Equals(check, factory->object_string())) {
3504    __ JumpIfSmi(v0, if_false);
3505    __ LoadRoot(at, Heap::kNullValueRootIndex);
3506    __ Branch(if_true, eq, v0, Operand(at));
3507    STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
3508    __ GetObjectType(v0, v0, a1);
3509    __ Branch(if_false, lt, a1, Operand(FIRST_JS_RECEIVER_TYPE));
3510    // Check for callable or undetectable objects => false.
3511    __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
3512    __ And(a1, a1,
3513           Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
3514    Split(eq, a1, Operand(zero_reg), if_true, if_false, fall_through);
3515// clang-format off
3516#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type)    \
3517  } else if (String::Equals(check, factory->type##_string())) {  \
3518    __ JumpIfSmi(v0, if_false);                                  \
3519    __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));      \
3520    __ LoadRoot(at, Heap::k##Type##MapRootIndex);                \
3521    Split(eq, v0, Operand(at), if_true, if_false, fall_through);
3522  SIMD128_TYPES(SIMD128_TYPE)
3523#undef SIMD128_TYPE
3524    // clang-format on
3525  } else {
3526    if (if_false != fall_through) __ jmp(if_false);
3527  }
3528  context()->Plug(if_true, if_false);
3529}
3530
3531
3532void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
3533  Comment cmnt(masm_, "[ CompareOperation");
3534
3535  // First we try a fast inlined version of the compare when one of
3536  // the operands is a literal.
3537  if (TryLiteralCompare(expr)) return;
3538
3539  // Always perform the comparison for its control flow.  Pack the result
3540  // into the expression's context after the comparison is performed.
3541  Label materialize_true, materialize_false;
3542  Label* if_true = NULL;
3543  Label* if_false = NULL;
3544  Label* fall_through = NULL;
3545  context()->PrepareTest(&materialize_true, &materialize_false,
3546                         &if_true, &if_false, &fall_through);
3547
3548  Token::Value op = expr->op();
3549  VisitForStackValue(expr->left());
3550  switch (op) {
3551    case Token::IN:
3552      VisitForStackValue(expr->right());
3553      SetExpressionPosition(expr);
3554      EmitHasProperty();
3555      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3556      __ LoadRoot(a4, Heap::kTrueValueRootIndex);
3557      Split(eq, v0, Operand(a4), if_true, if_false, fall_through);
3558      break;
3559
3560    case Token::INSTANCEOF: {
3561      VisitForAccumulatorValue(expr->right());
3562      SetExpressionPosition(expr);
3563      __ mov(a0, result_register());
3564      PopOperand(a1);
3565      InstanceOfStub stub(isolate());
3566      __ CallStub(&stub);
3567      PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
3568      __ LoadRoot(a4, Heap::kTrueValueRootIndex);
3569      Split(eq, v0, Operand(a4), if_true, if_false, fall_through);
3570      break;
3571    }
3572
3573    default: {
3574      VisitForAccumulatorValue(expr->right());
3575      SetExpressionPosition(expr);
3576      Condition cc = CompareIC::ComputeCondition(op);
3577      __ mov(a0, result_register());
3578      PopOperand(a1);
3579
3580      bool inline_smi_code = ShouldInlineSmiCase(op);
3581      JumpPatchSite patch_site(masm_);
3582      if (inline_smi_code) {
3583        Label slow_case;
3584        __ Or(a2, a0, Operand(a1));
3585        patch_site.EmitJumpIfNotSmi(a2, &slow_case);
3586        Split(cc, a1, Operand(a0), if_true, if_false, NULL);
3587        __ bind(&slow_case);
3588      }
3589
3590      Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3591      CallIC(ic, expr->CompareOperationFeedbackId());
3592      patch_site.EmitPatchInfo();
3593      PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3594      Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
3595    }
3596  }
3597
3598  // Convert the result of the comparison into one expected for this
3599  // expression's context.
3600  context()->Plug(if_true, if_false);
3601}
3602
3603
3604void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
3605                                              Expression* sub_expr,
3606                                              NilValue nil) {
3607  Label materialize_true, materialize_false;
3608  Label* if_true = NULL;
3609  Label* if_false = NULL;
3610  Label* fall_through = NULL;
3611  context()->PrepareTest(&materialize_true, &materialize_false,
3612                         &if_true, &if_false, &fall_through);
3613
3614  VisitForAccumulatorValue(sub_expr);
3615  PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3616  if (expr->op() == Token::EQ_STRICT) {
3617    Heap::RootListIndex nil_value = nil == kNullValue ?
3618        Heap::kNullValueRootIndex :
3619        Heap::kUndefinedValueRootIndex;
3620    __ LoadRoot(a1, nil_value);
3621    Split(eq, v0, Operand(a1), if_true, if_false, fall_through);
3622  } else {
3623    __ JumpIfSmi(v0, if_false);
3624    __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
3625    __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
3626    __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
3627    Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
3628  }
3629  context()->Plug(if_true, if_false);
3630}
3631
3632
3633Register FullCodeGenerator::result_register() {
3634  return v0;
3635}
3636
3637
3638Register FullCodeGenerator::context_register() {
3639  return cp;
3640}
3641
3642void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
3643  // DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3644  DCHECK(IsAligned(frame_offset, kPointerSize));
3645  //  __ sw(value, MemOperand(fp, frame_offset));
3646  __ ld(value, MemOperand(fp, frame_offset));
3647}
3648
3649void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
3650  // DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
3651  DCHECK(IsAligned(frame_offset, kPointerSize));
3652  //  __ sw(value, MemOperand(fp, frame_offset));
3653  __ sd(value, MemOperand(fp, frame_offset));
3654}
3655
3656
3657void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
3658  __ ld(dst, ContextMemOperand(cp, context_index));
3659}
3660
3661
3662void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
3663  Scope* closure_scope = scope()->ClosureScope();
3664  if (closure_scope->is_script_scope() ||
3665      closure_scope->is_module_scope()) {
3666    // Contexts nested in the native context have a canonical empty function
3667    // as their closure, not the anonymous closure containing the global
3668    // code.
3669    __ LoadNativeContextSlot(Context::CLOSURE_INDEX, at);
3670  } else if (closure_scope->is_eval_scope()) {
3671    // Contexts created by a call to eval have the same closure as the
3672    // context calling eval, not the anonymous closure containing the eval
3673    // code.  Fetch it from the context.
3674    __ ld(at, ContextMemOperand(cp, Context::CLOSURE_INDEX));
3675  } else {
3676    DCHECK(closure_scope->is_function_scope());
3677    __ ld(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
3678  }
3679  PushOperand(at);
3680}
3681
3682
3683// ----------------------------------------------------------------------------
3684// Non-local control flow support.
3685
3686void FullCodeGenerator::EnterFinallyBlock() {
3687  DCHECK(!result_register().is(a1));
3688  // Store pending message while executing finally block.
3689  ExternalReference pending_message_obj =
3690      ExternalReference::address_of_pending_message_obj(isolate());
3691  __ li(at, Operand(pending_message_obj));
3692  __ ld(a1, MemOperand(at));
3693  PushOperand(a1);
3694
3695  ClearPendingMessage();
3696}
3697
3698
3699void FullCodeGenerator::ExitFinallyBlock() {
3700  DCHECK(!result_register().is(a1));
3701  // Restore pending message from stack.
3702  PopOperand(a1);
3703  ExternalReference pending_message_obj =
3704      ExternalReference::address_of_pending_message_obj(isolate());
3705  __ li(at, Operand(pending_message_obj));
3706  __ sd(a1, MemOperand(at));
3707}
3708
3709
3710void FullCodeGenerator::ClearPendingMessage() {
3711  DCHECK(!result_register().is(a1));
3712  ExternalReference pending_message_obj =
3713      ExternalReference::address_of_pending_message_obj(isolate());
3714  __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
3715  __ li(at, Operand(pending_message_obj));
3716  __ sd(a1, MemOperand(at));
3717}
3718
3719
3720void FullCodeGenerator::DeferredCommands::EmitCommands() {
3721  __ Pop(result_register());  // Restore the accumulator.
3722  __ Pop(a1);                 // Get the token.
3723  for (DeferredCommand cmd : commands_) {
3724    Label skip;
3725    __ li(at, Operand(Smi::FromInt(cmd.token)));
3726    __ Branch(&skip, ne, a1, Operand(at));
3727    switch (cmd.command) {
3728      case kReturn:
3729        codegen_->EmitUnwindAndReturn();
3730        break;
3731      case kThrow:
3732        __ Push(result_register());
3733        __ CallRuntime(Runtime::kReThrow);
3734        break;
3735      case kContinue:
3736        codegen_->EmitContinue(cmd.target);
3737        break;
3738      case kBreak:
3739        codegen_->EmitBreak(cmd.target);
3740        break;
3741    }
3742    __ bind(&skip);
3743  }
3744}
3745
3746#undef __
3747
3748
3749void BackEdgeTable::PatchAt(Code* unoptimized_code,
3750                            Address pc,
3751                            BackEdgeState target_state,
3752                            Code* replacement_code) {
3753  static const int kInstrSize = Assembler::kInstrSize;
3754  Address pc_immediate_load_address =
3755      Assembler::target_address_from_return_address(pc);
3756  Address branch_address = pc_immediate_load_address - 2 * kInstrSize;
3757  Isolate* isolate = unoptimized_code->GetIsolate();
3758  CodePatcher patcher(isolate, branch_address, 1);
3759
3760  switch (target_state) {
3761    case INTERRUPT:
3762      // slt  at, a3, zero_reg (in case of count based interrupts)
3763      // beq  at, zero_reg, ok
3764      // lui  t9, <interrupt stub address> upper
3765      // ori  t9, <interrupt stub address> u-middle
3766      // dsll t9, t9, 16
3767      // ori  t9, <interrupt stub address> lower
3768      // jalr t9
3769      // nop
3770      // ok-label ----- pc_after points here
3771      patcher.masm()->slt(at, a3, zero_reg);
3772      break;
3773    case ON_STACK_REPLACEMENT:
3774      // addiu at, zero_reg, 1
3775      // beq  at, zero_reg, ok  ;; Not changed
3776      // lui  t9, <on-stack replacement address> upper
3777      // ori  t9, <on-stack replacement address> middle
3778      // dsll t9, t9, 16
3779      // ori  t9, <on-stack replacement address> lower
3780      // jalr t9  ;; Not changed
3781      // nop  ;; Not changed
3782      // ok-label ----- pc_after points here
3783      patcher.masm()->daddiu(at, zero_reg, 1);
3784      break;
3785  }
3786  // Replace the stack check address in the load-immediate (6-instr sequence)
3787  // with the entry address of the replacement code.
3788  Assembler::set_target_address_at(isolate, pc_immediate_load_address,
3789                                   replacement_code->entry());
3790
3791  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
3792      unoptimized_code, pc_immediate_load_address, replacement_code);
3793}
3794
3795
3796BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
3797    Isolate* isolate,
3798    Code* unoptimized_code,
3799    Address pc) {
3800  static const int kInstrSize = Assembler::kInstrSize;
3801  Address pc_immediate_load_address =
3802      Assembler::target_address_from_return_address(pc);
3803  Address branch_address = pc_immediate_load_address - 2 * kInstrSize;
3804
3805  DCHECK(Assembler::IsBeq(Assembler::instr_at(branch_address + kInstrSize)));
3806  if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) {
3807    DCHECK(reinterpret_cast<uint64_t>(
3808        Assembler::target_address_at(pc_immediate_load_address)) ==
3809           reinterpret_cast<uint64_t>(
3810               isolate->builtins()->InterruptCheck()->entry()));
3811    return INTERRUPT;
3812  }
3813
3814  DCHECK(Assembler::IsAddImmediate(Assembler::instr_at(branch_address)));
3815
3816  DCHECK(reinterpret_cast<uint64_t>(
3817             Assembler::target_address_at(pc_immediate_load_address)) ==
3818         reinterpret_cast<uint64_t>(
3819             isolate->builtins()->OnStackReplacement()->entry()));
3820  return ON_STACK_REPLACEMENT;
3821}
3822
3823
3824}  // namespace internal
3825}  // namespace v8
3826
3827#endif  // V8_TARGET_ARCH_MIPS64
3828