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