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