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