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