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