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