full-codegen.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
1// Copyright 2011 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#include "codegen.h"
31#include "compiler.h"
32#include "debug.h"
33#include "full-codegen.h"
34#include "liveedit.h"
35#include "macro-assembler.h"
36#include "prettyprinter.h"
37#include "scopes.h"
38#include "scopeinfo.h"
39#include "stub-cache.h"
40
41namespace v8 {
42namespace internal {
43
44void BreakableStatementChecker::Check(Statement* stmt) {
45  Visit(stmt);
46}
47
48
49void BreakableStatementChecker::Check(Expression* expr) {
50  Visit(expr);
51}
52
53
54void BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
55}
56
57
58void BreakableStatementChecker::VisitBlock(Block* stmt) {
59}
60
61
62void BreakableStatementChecker::VisitExpressionStatement(
63    ExpressionStatement* stmt) {
64  // Check if expression is breakable.
65  Visit(stmt->expression());
66}
67
68
69void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
70}
71
72
73void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
74  // If the condition is breakable the if statement is breakable.
75  Visit(stmt->condition());
76}
77
78
79void BreakableStatementChecker::VisitContinueStatement(
80    ContinueStatement* stmt) {
81}
82
83
84void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
85}
86
87
88void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
89  // Return is breakable if the expression is.
90  Visit(stmt->expression());
91}
92
93
94void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
95  Visit(stmt->expression());
96}
97
98
99void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
100  // Switch statements breakable if the tag expression is.
101  Visit(stmt->tag());
102}
103
104
105void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
106  // Mark do while as breakable to avoid adding a break slot in front of it.
107  is_breakable_ = true;
108}
109
110
111void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
112  // Mark while statements breakable if the condition expression is.
113  Visit(stmt->cond());
114}
115
116
117void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
118  // Mark for statements breakable if the condition expression is.
119  if (stmt->cond() != NULL) {
120    Visit(stmt->cond());
121  }
122}
123
124
125void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
126  // Mark for in statements breakable if the enumerable expression is.
127  Visit(stmt->enumerable());
128}
129
130
131void BreakableStatementChecker::VisitTryCatchStatement(
132    TryCatchStatement* stmt) {
133  // Mark try catch as breakable to avoid adding a break slot in front of it.
134  is_breakable_ = true;
135}
136
137
138void BreakableStatementChecker::VisitTryFinallyStatement(
139    TryFinallyStatement* stmt) {
140  // Mark try finally as breakable to avoid adding a break slot in front of it.
141  is_breakable_ = true;
142}
143
144
145void BreakableStatementChecker::VisitDebuggerStatement(
146    DebuggerStatement* stmt) {
147  // The debugger statement is breakable.
148  is_breakable_ = true;
149}
150
151
152void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
153}
154
155
156void BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
157    SharedFunctionInfoLiteral* expr) {
158}
159
160
161void BreakableStatementChecker::VisitConditional(Conditional* expr) {
162}
163
164
165void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
166}
167
168
169void BreakableStatementChecker::VisitLiteral(Literal* expr) {
170}
171
172
173void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
174}
175
176
177void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
178}
179
180
181void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
182}
183
184
185void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
186  // If assigning to a property (including a global property) the assignment is
187  // breakable.
188  VariableProxy* proxy = expr->target()->AsVariableProxy();
189  Property* prop = expr->target()->AsProperty();
190  if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
191    is_breakable_ = true;
192    return;
193  }
194
195  // Otherwise the assignment is breakable if the assigned value is.
196  Visit(expr->value());
197}
198
199
200void BreakableStatementChecker::VisitThrow(Throw* expr) {
201  // Throw is breakable if the expression is.
202  Visit(expr->exception());
203}
204
205
206void BreakableStatementChecker::VisitProperty(Property* expr) {
207  // Property load is breakable.
208  is_breakable_ = true;
209}
210
211
212void BreakableStatementChecker::VisitCall(Call* expr) {
213  // Function calls both through IC and call stub are breakable.
214  is_breakable_ = true;
215}
216
217
218void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
219  // Function calls through new are breakable.
220  is_breakable_ = true;
221}
222
223
224void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
225}
226
227
228void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
229  Visit(expr->expression());
230}
231
232
233void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
234  Visit(expr->expression());
235}
236
237
238void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
239  Visit(expr->left());
240  if (expr->op() != Token::AND &&
241      expr->op() != Token::OR) {
242    Visit(expr->right());
243  }
244}
245
246
247void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
248  Visit(expr->left());
249  Visit(expr->right());
250}
251
252
253void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
254}
255
256
257#define __ ACCESS_MASM(masm())
258
259bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
260  Isolate* isolate = info->isolate();
261  Handle<Script> script = info->script();
262  if (!script->IsUndefined() && !script->source()->IsUndefined()) {
263    int len = String::cast(script->source())->length();
264    isolate->counters()->total_full_codegen_source_size()->Increment(len);
265  }
266  if (FLAG_trace_codegen) {
267    PrintF("Full Compiler - ");
268  }
269  CodeGenerator::MakeCodePrologue(info);
270  const int kInitialBufferSize = 4 * KB;
271  MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
272#ifdef ENABLE_GDB_JIT_INTERFACE
273  masm.positions_recorder()->StartGDBJITLineInfoRecording();
274#endif
275
276  FullCodeGenerator cgen(&masm);
277  cgen.Generate(info);
278  if (cgen.HasStackOverflow()) {
279    ASSERT(!isolate->has_pending_exception());
280    return false;
281  }
282  unsigned table_offset = cgen.EmitStackCheckTable();
283
284  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
285  Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
286  code->set_optimizable(info->IsOptimizable());
287  cgen.PopulateDeoptimizationData(code);
288  code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
289  code->set_handler_table(*cgen.handler_table());
290#ifdef ENABLE_DEBUGGER_SUPPORT
291  code->set_has_debug_break_slots(
292      info->isolate()->debugger()->IsDebuggerActive());
293  code->set_compiled_optimizable(info->IsOptimizable());
294#endif  // ENABLE_DEBUGGER_SUPPORT
295  code->set_allow_osr_at_loop_nesting_level(0);
296  code->set_stack_check_table_offset(table_offset);
297  CodeGenerator::PrintCode(code, info);
298  info->SetCode(code);  // May be an empty handle.
299#ifdef ENABLE_GDB_JIT_INTERFACE
300  if (FLAG_gdbjit && !code.is_null()) {
301    GDBJITLineInfo* lineinfo =
302        masm.positions_recorder()->DetachGDBJITLineInfo();
303
304    GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
305  }
306#endif
307  return !code.is_null();
308}
309
310
311unsigned FullCodeGenerator::EmitStackCheckTable() {
312  // The stack check table consists of a length (in number of entries)
313  // field, and then a sequence of entries.  Each entry is a pair of AST id
314  // and code-relative pc offset.
315  masm()->Align(kIntSize);
316  unsigned offset = masm()->pc_offset();
317  unsigned length = stack_checks_.length();
318  __ dd(length);
319  for (unsigned i = 0; i < length; ++i) {
320    __ dd(stack_checks_[i].id);
321    __ dd(stack_checks_[i].pc_and_state);
322  }
323  return offset;
324}
325
326
327void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
328  // Fill in the deoptimization information.
329  ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
330  if (!info_->HasDeoptimizationSupport()) return;
331  int length = bailout_entries_.length();
332  Handle<DeoptimizationOutputData> data =
333      isolate()->factory()->
334      NewDeoptimizationOutputData(length, TENURED);
335  for (int i = 0; i < length; i++) {
336    data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
337    data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
338  }
339  code->set_deoptimization_data(*data);
340}
341
342
343void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
344  PrepareForBailoutForId(node->id(), state);
345}
346
347
348void FullCodeGenerator::RecordJSReturnSite(Call* call) {
349  // We record the offset of the function return so we can rebuild the frame
350  // if the function was inlined, i.e., this is the return address in the
351  // inlined function's frame.
352  //
353  // The state is ignored.  We defensively set it to TOS_REG, which is the
354  // real state of the unoptimized code at the return site.
355  PrepareForBailoutForId(call->ReturnId(), TOS_REG);
356#ifdef DEBUG
357  // In debug builds, mark the return so we can verify that this function
358  // was called.
359  ASSERT(!call->return_is_recorded_);
360  call->return_is_recorded_ = true;
361#endif
362}
363
364
365void FullCodeGenerator::PrepareForBailoutForId(unsigned id, State state) {
366  // There's no need to prepare this code for bailouts from already optimized
367  // code or code that can't be optimized.
368  if (!FLAG_deopt || !info_->HasDeoptimizationSupport()) return;
369  unsigned pc_and_state =
370      StateField::encode(state) | PcField::encode(masm_->pc_offset());
371  BailoutEntry entry = { id, pc_and_state };
372#ifdef DEBUG
373  // Assert that we don't have multiple bailout entries for the same node.
374  for (int i = 0; i < bailout_entries_.length(); i++) {
375    if (bailout_entries_.at(i).id == entry.id) {
376      AstPrinter printer;
377      PrintF("%s", printer.PrintProgram(info_->function()));
378      UNREACHABLE();
379    }
380  }
381#endif  // DEBUG
382  bailout_entries_.Add(entry);
383}
384
385
386void FullCodeGenerator::RecordStackCheck(unsigned ast_id) {
387  // The pc offset does not need to be encoded and packed together with a
388  // state.
389  ASSERT(masm_->pc_offset() > 0);
390  BailoutEntry entry = { ast_id, static_cast<unsigned>(masm_->pc_offset()) };
391  stack_checks_.Add(entry);
392}
393
394
395bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
396  // Inline smi case inside loops, but not division and modulo which
397  // are too complicated and take up too much space.
398  if (op == Token::DIV ||op == Token::MOD) return false;
399  if (FLAG_always_inline_smi_code) return true;
400  return loop_depth_ > 0;
401}
402
403
404void FullCodeGenerator::EffectContext::Plug(Register reg) const {
405}
406
407
408void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
409  __ Move(result_register(), reg);
410}
411
412
413void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
414  __ push(reg);
415}
416
417
418void FullCodeGenerator::TestContext::Plug(Register reg) const {
419  // For simplicity we always test the accumulator register.
420  __ Move(result_register(), reg);
421  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
422  codegen()->DoTest(this);
423}
424
425
426void FullCodeGenerator::EffectContext::PlugTOS() const {
427  __ Drop(1);
428}
429
430
431void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
432  __ pop(result_register());
433}
434
435
436void FullCodeGenerator::StackValueContext::PlugTOS() const {
437}
438
439
440void FullCodeGenerator::TestContext::PlugTOS() const {
441  // For simplicity we always test the accumulator register.
442  __ pop(result_register());
443  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
444  codegen()->DoTest(this);
445}
446
447
448void FullCodeGenerator::EffectContext::PrepareTest(
449    Label* materialize_true,
450    Label* materialize_false,
451    Label** if_true,
452    Label** if_false,
453    Label** fall_through) const {
454  // In an effect context, the true and the false case branch to the
455  // same label.
456  *if_true = *if_false = *fall_through = materialize_true;
457}
458
459
460void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
461    Label* materialize_true,
462    Label* materialize_false,
463    Label** if_true,
464    Label** if_false,
465    Label** fall_through) const {
466  *if_true = *fall_through = materialize_true;
467  *if_false = materialize_false;
468}
469
470
471void FullCodeGenerator::StackValueContext::PrepareTest(
472    Label* materialize_true,
473    Label* materialize_false,
474    Label** if_true,
475    Label** if_false,
476    Label** fall_through) const {
477  *if_true = *fall_through = materialize_true;
478  *if_false = materialize_false;
479}
480
481
482void FullCodeGenerator::TestContext::PrepareTest(
483    Label* materialize_true,
484    Label* materialize_false,
485    Label** if_true,
486    Label** if_false,
487    Label** fall_through) const {
488  *if_true = true_label_;
489  *if_false = false_label_;
490  *fall_through = fall_through_;
491}
492
493
494void FullCodeGenerator::DoTest(const TestContext* context) {
495  DoTest(context->condition(),
496         context->true_label(),
497         context->false_label(),
498         context->fall_through());
499}
500
501
502void FullCodeGenerator::VisitDeclarations(
503    ZoneList<Declaration*>* declarations) {
504  int length = declarations->length();
505  int global_count = 0;
506  for (int i = 0; i < length; i++) {
507    Declaration* decl = declarations->at(i);
508    EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
509  }
510
511  // Batch declare global functions and variables.
512  if (global_count > 0) {
513    Handle<FixedArray> array =
514        isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
515    for (int j = 0, i = 0; i < length; i++) {
516      Declaration* decl = declarations->at(i);
517      Variable* var = decl->proxy()->var();
518
519      if (var->IsUnallocated()) {
520        array->set(j++, *(var->name()));
521        if (decl->fun() == NULL) {
522          if (var->binding_needs_init()) {
523            // In case this binding needs initialization use the hole.
524            array->set_the_hole(j++);
525          } else {
526            array->set_undefined(j++);
527          }
528        } else {
529          Handle<SharedFunctionInfo> function =
530              Compiler::BuildFunctionInfo(decl->fun(), script());
531          // Check for stack-overflow exception.
532          if (function.is_null()) {
533            SetStackOverflow();
534            return;
535          }
536          array->set(j++, *function);
537        }
538      }
539    }
540    // Invoke the platform-dependent code generator to do the actual
541    // declaration the global functions and variables.
542    DeclareGlobals(array);
543  }
544}
545
546
547int FullCodeGenerator::DeclareGlobalsFlags() {
548  ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
549  return DeclareGlobalsEvalFlag::encode(is_eval()) |
550      DeclareGlobalsNativeFlag::encode(is_native()) |
551      DeclareGlobalsLanguageMode::encode(language_mode());
552}
553
554
555void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
556  CodeGenerator::RecordPositions(masm_, fun->start_position());
557}
558
559
560void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
561  CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
562}
563
564
565void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
566#ifdef ENABLE_DEBUGGER_SUPPORT
567  if (!isolate()->debugger()->IsDebuggerActive()) {
568    CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
569  } else {
570    // Check if the statement will be breakable without adding a debug break
571    // slot.
572    BreakableStatementChecker checker;
573    checker.Check(stmt);
574    // Record the statement position right here if the statement is not
575    // breakable. For breakable statements the actual recording of the
576    // position will be postponed to the breakable code (typically an IC).
577    bool position_recorded = CodeGenerator::RecordPositions(
578        masm_, stmt->statement_pos(), !checker.is_breakable());
579    // If the position recording did record a new position generate a debug
580    // break slot to make the statement breakable.
581    if (position_recorded) {
582      Debug::GenerateSlot(masm_);
583    }
584  }
585#else
586  CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
587#endif
588}
589
590
591void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
592#ifdef ENABLE_DEBUGGER_SUPPORT
593  if (!isolate()->debugger()->IsDebuggerActive()) {
594    CodeGenerator::RecordPositions(masm_, pos);
595  } else {
596    // Check if the expression will be breakable without adding a debug break
597    // slot.
598    BreakableStatementChecker checker;
599    checker.Check(expr);
600    // Record a statement position right here if the expression is not
601    // breakable. For breakable expressions the actual recording of the
602    // position will be postponed to the breakable code (typically an IC).
603    // NOTE this will record a statement position for something which might
604    // not be a statement. As stepping in the debugger will only stop at
605    // statement positions this is used for e.g. the condition expression of
606    // a do while loop.
607    bool position_recorded = CodeGenerator::RecordPositions(
608        masm_, pos, !checker.is_breakable());
609    // If the position recording did record a new position generate a debug
610    // break slot to make the statement breakable.
611    if (position_recorded) {
612      Debug::GenerateSlot(masm_);
613    }
614  }
615#else
616  CodeGenerator::RecordPositions(masm_, pos);
617#endif
618}
619
620
621void FullCodeGenerator::SetStatementPosition(int pos) {
622  CodeGenerator::RecordPositions(masm_, pos);
623}
624
625
626void FullCodeGenerator::SetSourcePosition(int pos) {
627  if (pos != RelocInfo::kNoPosition) {
628    masm_->positions_recorder()->RecordPosition(pos);
629  }
630}
631
632
633// Lookup table for code generators for  special runtime calls which are
634// generated inline.
635#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)          \
636    &FullCodeGenerator::Emit##Name,
637
638const FullCodeGenerator::InlineFunctionGenerator
639  FullCodeGenerator::kInlineFunctionGenerators[] = {
640    INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
641    INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
642  };
643#undef INLINE_FUNCTION_GENERATOR_ADDRESS
644
645
646FullCodeGenerator::InlineFunctionGenerator
647  FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
648    int lookup_index =
649        static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
650    ASSERT(lookup_index >= 0);
651    ASSERT(static_cast<size_t>(lookup_index) <
652           ARRAY_SIZE(kInlineFunctionGenerators));
653    return kInlineFunctionGenerators[lookup_index];
654}
655
656
657void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
658  const Runtime::Function* function = expr->function();
659  ASSERT(function != NULL);
660  ASSERT(function->intrinsic_type == Runtime::INLINE);
661  InlineFunctionGenerator generator =
662      FindInlineFunctionGenerator(function->function_id);
663  ((*this).*(generator))(expr);
664}
665
666
667void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
668  switch (expr->op()) {
669    case Token::COMMA:
670      return VisitComma(expr);
671    case Token::OR:
672    case Token::AND:
673      return VisitLogicalExpression(expr);
674    default:
675      return VisitArithmeticExpression(expr);
676  }
677}
678
679
680void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
681  if (context()->IsEffect()) {
682    VisitForEffect(expr);
683  } else if (context()->IsAccumulatorValue()) {
684    VisitForAccumulatorValue(expr);
685  } else if (context()->IsStackValue()) {
686    VisitForStackValue(expr);
687  } else if (context()->IsTest()) {
688    const TestContext* test = TestContext::cast(context());
689    VisitForControl(expr, test->true_label(), test->false_label(),
690                    test->fall_through());
691  }
692}
693
694
695void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
696  Comment cmnt(masm_, "[ Comma");
697  VisitForEffect(expr->left());
698  VisitInDuplicateContext(expr->right());
699}
700
701
702void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
703  bool is_logical_and = expr->op() == Token::AND;
704  Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
705  Expression* left = expr->left();
706  Expression* right = expr->right();
707  int right_id = expr->RightId();
708  Label done;
709
710  if (context()->IsTest()) {
711    Label eval_right;
712    const TestContext* test = TestContext::cast(context());
713    if (is_logical_and) {
714      VisitForControl(left, &eval_right, test->false_label(), &eval_right);
715    } else {
716      VisitForControl(left, test->true_label(), &eval_right, &eval_right);
717    }
718    PrepareForBailoutForId(right_id, NO_REGISTERS);
719    __ bind(&eval_right);
720
721  } else if (context()->IsAccumulatorValue()) {
722    VisitForAccumulatorValue(left);
723    // We want the value in the accumulator for the test, and on the stack in
724    // case we need it.
725    __ push(result_register());
726    Label discard, restore;
727    if (is_logical_and) {
728      DoTest(left, &discard, &restore, &restore);
729    } else {
730      DoTest(left, &restore, &discard, &restore);
731    }
732    __ bind(&restore);
733    __ pop(result_register());
734    __ jmp(&done);
735    __ bind(&discard);
736    __ Drop(1);
737    PrepareForBailoutForId(right_id, NO_REGISTERS);
738
739  } else if (context()->IsStackValue()) {
740    VisitForAccumulatorValue(left);
741    // We want the value in the accumulator for the test, and on the stack in
742    // case we need it.
743    __ push(result_register());
744    Label discard;
745    if (is_logical_and) {
746      DoTest(left, &discard, &done, &discard);
747    } else {
748      DoTest(left, &done, &discard, &discard);
749    }
750    __ bind(&discard);
751    __ Drop(1);
752    PrepareForBailoutForId(right_id, NO_REGISTERS);
753
754  } else {
755    ASSERT(context()->IsEffect());
756    Label eval_right;
757    if (is_logical_and) {
758      VisitForControl(left, &eval_right, &done, &eval_right);
759    } else {
760      VisitForControl(left, &done, &eval_right, &eval_right);
761    }
762    PrepareForBailoutForId(right_id, NO_REGISTERS);
763    __ bind(&eval_right);
764  }
765
766  VisitInDuplicateContext(right);
767  __ bind(&done);
768}
769
770
771void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
772  Token::Value op = expr->op();
773  Comment cmnt(masm_, "[ ArithmeticExpression");
774  Expression* left = expr->left();
775  Expression* right = expr->right();
776  OverwriteMode mode =
777      left->ResultOverwriteAllowed()
778      ? OVERWRITE_LEFT
779      : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
780
781  VisitForStackValue(left);
782  VisitForAccumulatorValue(right);
783
784  SetSourcePosition(expr->position());
785  if (ShouldInlineSmiCase(op)) {
786    EmitInlineSmiBinaryOp(expr, op, mode, left, right);
787  } else {
788    EmitBinaryOp(expr, op, mode);
789  }
790}
791
792
793void FullCodeGenerator::VisitBlock(Block* stmt) {
794  Comment cmnt(masm_, "[ Block");
795  NestedBlock nested_block(this, stmt);
796  SetStatementPosition(stmt);
797
798  Scope* saved_scope = scope();
799  // Push a block context when entering a block with block scoped variables.
800  if (stmt->block_scope() != NULL) {
801    { Comment cmnt(masm_, "[ Extend block context");
802      scope_ = stmt->block_scope();
803      Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
804      int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
805      __ Push(scope_info);
806      PushFunctionArgumentForContextAllocation();
807      if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
808        FastNewBlockContextStub stub(heap_slots);
809        __ CallStub(&stub);
810      } else {
811        __ CallRuntime(Runtime::kPushBlockContext, 2);
812      }
813
814      // Replace the context stored in the frame.
815      StoreToFrameField(StandardFrameConstants::kContextOffset,
816                        context_register());
817    }
818    { Comment cmnt(masm_, "[ Declarations");
819      VisitDeclarations(scope_->declarations());
820    }
821  }
822  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
823  VisitStatements(stmt->statements());
824  scope_ = saved_scope;
825  __ bind(nested_block.break_label());
826  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
827
828  // Pop block context if necessary.
829  if (stmt->block_scope() != NULL) {
830    LoadContextField(context_register(), Context::PREVIOUS_INDEX);
831    // Update local stack frame context field.
832    StoreToFrameField(StandardFrameConstants::kContextOffset,
833                      context_register());
834  }
835}
836
837
838void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
839  Comment cmnt(masm_, "[ ExpressionStatement");
840  SetStatementPosition(stmt);
841  VisitForEffect(stmt->expression());
842}
843
844
845void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
846  Comment cmnt(masm_, "[ EmptyStatement");
847  SetStatementPosition(stmt);
848}
849
850
851void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
852  Comment cmnt(masm_, "[ IfStatement");
853  SetStatementPosition(stmt);
854  Label then_part, else_part, done;
855
856  if (stmt->HasElseStatement()) {
857    VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
858    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
859    __ bind(&then_part);
860    Visit(stmt->then_statement());
861    __ jmp(&done);
862
863    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
864    __ bind(&else_part);
865    Visit(stmt->else_statement());
866  } else {
867    VisitForControl(stmt->condition(), &then_part, &done, &then_part);
868    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
869    __ bind(&then_part);
870    Visit(stmt->then_statement());
871
872    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
873  }
874  __ bind(&done);
875  PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
876}
877
878
879void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
880  Comment cmnt(masm_,  "[ ContinueStatement");
881  SetStatementPosition(stmt);
882  NestedStatement* current = nesting_stack_;
883  int stack_depth = 0;
884  int context_length = 0;
885  // When continuing, we clobber the unpredictable value in the accumulator
886  // with one that's safe for GC.  If we hit an exit from the try block of
887  // try...finally on our way out, we will unconditionally preserve the
888  // accumulator on the stack.
889  ClearAccumulator();
890  while (!current->IsContinueTarget(stmt->target())) {
891    current = current->Exit(&stack_depth, &context_length);
892  }
893  __ Drop(stack_depth);
894  if (context_length > 0) {
895    while (context_length > 0) {
896      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
897      --context_length;
898    }
899    StoreToFrameField(StandardFrameConstants::kContextOffset,
900                      context_register());
901  }
902
903  __ jmp(current->AsIteration()->continue_label());
904}
905
906
907void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
908  Comment cmnt(masm_,  "[ BreakStatement");
909  SetStatementPosition(stmt);
910  NestedStatement* current = nesting_stack_;
911  int stack_depth = 0;
912  int context_length = 0;
913  // When breaking, we clobber the unpredictable value in the accumulator
914  // with one that's safe for GC.  If we hit an exit from the try block of
915  // try...finally on our way out, we will unconditionally preserve the
916  // accumulator on the stack.
917  ClearAccumulator();
918  while (!current->IsBreakTarget(stmt->target())) {
919    current = current->Exit(&stack_depth, &context_length);
920  }
921  __ Drop(stack_depth);
922  if (context_length > 0) {
923    while (context_length > 0) {
924      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
925      --context_length;
926    }
927    StoreToFrameField(StandardFrameConstants::kContextOffset,
928                      context_register());
929  }
930
931  __ jmp(current->AsBreakable()->break_label());
932}
933
934
935void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
936  Comment cmnt(masm_, "[ ReturnStatement");
937  SetStatementPosition(stmt);
938  Expression* expr = stmt->expression();
939  VisitForAccumulatorValue(expr);
940
941  // Exit all nested statements.
942  NestedStatement* current = nesting_stack_;
943  int stack_depth = 0;
944  int context_length = 0;
945  while (current != NULL) {
946    current = current->Exit(&stack_depth, &context_length);
947  }
948  __ Drop(stack_depth);
949
950  EmitReturnSequence();
951}
952
953
954void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
955  Comment cmnt(masm_, "[ WithStatement");
956  SetStatementPosition(stmt);
957
958  VisitForStackValue(stmt->expression());
959  PushFunctionArgumentForContextAllocation();
960  __ CallRuntime(Runtime::kPushWithContext, 2);
961  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
962
963  { WithOrCatch body(this);
964    Visit(stmt->statement());
965  }
966
967  // Pop context.
968  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
969  // Update local stack frame context field.
970  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
971}
972
973
974void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
975  Comment cmnt(masm_, "[ DoWhileStatement");
976  SetStatementPosition(stmt);
977  Label body, stack_check;
978
979  Iteration loop_statement(this, stmt);
980  increment_loop_depth();
981
982  __ bind(&body);
983  Visit(stmt->body());
984
985  // Record the position of the do while condition and make sure it is
986  // possible to break on the condition.
987  __ bind(loop_statement.continue_label());
988  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
989  SetExpressionPosition(stmt->cond(), stmt->condition_position());
990  VisitForControl(stmt->cond(),
991                  &stack_check,
992                  loop_statement.break_label(),
993                  &stack_check);
994
995  // Check stack before looping.
996  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
997  __ bind(&stack_check);
998  EmitStackCheck(stmt);
999  __ jmp(&body);
1000
1001  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1002  __ bind(loop_statement.break_label());
1003  decrement_loop_depth();
1004}
1005
1006
1007void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1008  Comment cmnt(masm_, "[ WhileStatement");
1009  Label test, body;
1010
1011  Iteration loop_statement(this, stmt);
1012  increment_loop_depth();
1013
1014  // Emit the test at the bottom of the loop.
1015  __ jmp(&test);
1016
1017  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1018  __ bind(&body);
1019  Visit(stmt->body());
1020
1021  // Emit the statement position here as this is where the while
1022  // statement code starts.
1023  __ bind(loop_statement.continue_label());
1024  SetStatementPosition(stmt);
1025
1026  // Check stack before looping.
1027  EmitStackCheck(stmt);
1028
1029  __ bind(&test);
1030  VisitForControl(stmt->cond(),
1031                  &body,
1032                  loop_statement.break_label(),
1033                  loop_statement.break_label());
1034
1035  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1036  __ bind(loop_statement.break_label());
1037  decrement_loop_depth();
1038}
1039
1040
1041void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1042  Comment cmnt(masm_, "[ ForStatement");
1043  Label test, body;
1044
1045  Iteration loop_statement(this, stmt);
1046  if (stmt->init() != NULL) {
1047    Visit(stmt->init());
1048  }
1049
1050  increment_loop_depth();
1051  // Emit the test at the bottom of the loop (even if empty).
1052  __ jmp(&test);
1053
1054  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1055  __ bind(&body);
1056  Visit(stmt->body());
1057
1058  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1059  __ bind(loop_statement.continue_label());
1060  SetStatementPosition(stmt);
1061  if (stmt->next() != NULL) {
1062    Visit(stmt->next());
1063  }
1064
1065  // Emit the statement position here as this is where the for
1066  // statement code starts.
1067  SetStatementPosition(stmt);
1068
1069  // Check stack before looping.
1070  EmitStackCheck(stmt);
1071
1072  __ bind(&test);
1073  if (stmt->cond() != NULL) {
1074    VisitForControl(stmt->cond(),
1075                    &body,
1076                    loop_statement.break_label(),
1077                    loop_statement.break_label());
1078  } else {
1079    __ jmp(&body);
1080  }
1081
1082  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1083  __ bind(loop_statement.break_label());
1084  decrement_loop_depth();
1085}
1086
1087
1088void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1089  Comment cmnt(masm_, "[ TryCatchStatement");
1090  SetStatementPosition(stmt);
1091  // The try block adds a handler to the exception handler chain before
1092  // entering, and removes it again when exiting normally.  If an exception
1093  // is thrown during execution of the try block, the handler is consumed
1094  // and control is passed to the catch block with the exception in the
1095  // result register.
1096
1097  Label try_entry, handler_entry, exit;
1098  __ jmp(&try_entry);
1099  __ bind(&handler_entry);
1100  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1101  // Exception handler code, the exception is in the result register.
1102  // Extend the context before executing the catch block.
1103  { Comment cmnt(masm_, "[ Extend catch context");
1104    __ Push(stmt->variable()->name());
1105    __ push(result_register());
1106    PushFunctionArgumentForContextAllocation();
1107    __ CallRuntime(Runtime::kPushCatchContext, 3);
1108    StoreToFrameField(StandardFrameConstants::kContextOffset,
1109                      context_register());
1110  }
1111
1112  Scope* saved_scope = scope();
1113  scope_ = stmt->scope();
1114  ASSERT(scope_->declarations()->is_empty());
1115  { WithOrCatch catch_body(this);
1116    Visit(stmt->catch_block());
1117  }
1118  // Restore the context.
1119  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1120  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1121  scope_ = saved_scope;
1122  __ jmp(&exit);
1123
1124  // Try block code. Sets up the exception handler chain.
1125  __ bind(&try_entry);
1126  __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER, stmt->index());
1127  { TryCatch try_body(this);
1128    Visit(stmt->try_block());
1129  }
1130  __ PopTryHandler();
1131  __ bind(&exit);
1132}
1133
1134
1135void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1136  Comment cmnt(masm_, "[ TryFinallyStatement");
1137  SetStatementPosition(stmt);
1138  // Try finally is compiled by setting up a try-handler on the stack while
1139  // executing the try body, and removing it again afterwards.
1140  //
1141  // The try-finally construct can enter the finally block in three ways:
1142  // 1. By exiting the try-block normally. This removes the try-handler and
1143  //    calls the finally block code before continuing.
1144  // 2. By exiting the try-block with a function-local control flow transfer
1145  //    (break/continue/return). The site of the, e.g., break removes the
1146  //    try handler and calls the finally block code before continuing
1147  //    its outward control transfer.
1148  // 3. By exiting the try-block with a thrown exception.
1149  //    This can happen in nested function calls. It traverses the try-handler
1150  //    chain and consumes the try-handler entry before jumping to the
1151  //    handler code. The handler code then calls the finally-block before
1152  //    rethrowing the exception.
1153  //
1154  // The finally block must assume a return address on top of the stack
1155  // (or in the link register on ARM chips) and a value (return value or
1156  // exception) in the result register (rax/eax/r0), both of which must
1157  // be preserved. The return address isn't GC-safe, so it should be
1158  // cooked before GC.
1159  Label try_entry, handler_entry, finally_entry;
1160
1161  // Jump to try-handler setup and try-block code.
1162  __ jmp(&try_entry);
1163  __ bind(&handler_entry);
1164  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1165  // Exception handler code.  This code is only executed when an exception
1166  // is thrown.  The exception is in the result register, and must be
1167  // preserved by the finally block.  Call the finally block and then
1168  // rethrow the exception if it returns.
1169  __ Call(&finally_entry);
1170  __ push(result_register());
1171  __ CallRuntime(Runtime::kReThrow, 1);
1172
1173  // Finally block implementation.
1174  __ bind(&finally_entry);
1175  EnterFinallyBlock();
1176  { Finally finally_body(this);
1177    Visit(stmt->finally_block());
1178  }
1179  ExitFinallyBlock();  // Return to the calling code.
1180
1181  // Setup try handler.
1182  __ bind(&try_entry);
1183  __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER, stmt->index());
1184  { TryFinally try_body(this, &finally_entry);
1185    Visit(stmt->try_block());
1186  }
1187  __ PopTryHandler();
1188  // Execute the finally block on the way out.  Clobber the unpredictable
1189  // value in the result register with one that's safe for GC because the
1190  // finally block will unconditionally preserve the result register on the
1191  // stack.
1192  ClearAccumulator();
1193  __ Call(&finally_entry);
1194}
1195
1196
1197void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1198#ifdef ENABLE_DEBUGGER_SUPPORT
1199  Comment cmnt(masm_, "[ DebuggerStatement");
1200  SetStatementPosition(stmt);
1201
1202  __ DebugBreak();
1203  // Ignore the return value.
1204#endif
1205}
1206
1207
1208void FullCodeGenerator::VisitConditional(Conditional* expr) {
1209  Comment cmnt(masm_, "[ Conditional");
1210  Label true_case, false_case, done;
1211  VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1212
1213  PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
1214  __ bind(&true_case);
1215  SetExpressionPosition(expr->then_expression(),
1216                        expr->then_expression_position());
1217  if (context()->IsTest()) {
1218    const TestContext* for_test = TestContext::cast(context());
1219    VisitForControl(expr->then_expression(),
1220                    for_test->true_label(),
1221                    for_test->false_label(),
1222                    NULL);
1223  } else {
1224    VisitInDuplicateContext(expr->then_expression());
1225    __ jmp(&done);
1226  }
1227
1228  PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1229  __ bind(&false_case);
1230  SetExpressionPosition(expr->else_expression(),
1231                        expr->else_expression_position());
1232  VisitInDuplicateContext(expr->else_expression());
1233  // If control flow falls through Visit, merge it with true case here.
1234  if (!context()->IsTest()) {
1235    __ bind(&done);
1236  }
1237}
1238
1239
1240void FullCodeGenerator::VisitLiteral(Literal* expr) {
1241  Comment cmnt(masm_, "[ Literal");
1242  context()->Plug(expr->handle());
1243}
1244
1245
1246void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1247  Comment cmnt(masm_, "[ FunctionLiteral");
1248
1249  // Build the function boilerplate and instantiate it.
1250  Handle<SharedFunctionInfo> function_info =
1251      Compiler::BuildFunctionInfo(expr, script());
1252  if (function_info.is_null()) {
1253    SetStackOverflow();
1254    return;
1255  }
1256  EmitNewClosure(function_info, expr->pretenure());
1257}
1258
1259
1260void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1261    SharedFunctionInfoLiteral* expr) {
1262  Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
1263  EmitNewClosure(expr->shared_function_info(), false);
1264}
1265
1266
1267void FullCodeGenerator::VisitThrow(Throw* expr) {
1268  Comment cmnt(masm_, "[ Throw");
1269  VisitForStackValue(expr->exception());
1270  __ CallRuntime(Runtime::kThrow, 1);
1271  // Never returns here.
1272}
1273
1274
1275FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1276    int* stack_depth,
1277    int* context_length) {
1278  // The macros used here must preserve the result register.
1279  __ Drop(*stack_depth);
1280  __ PopTryHandler();
1281  *stack_depth = 0;
1282  return previous_;
1283}
1284
1285
1286bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1287  Expression *sub_expr;
1288  Handle<String> check;
1289  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1290    EmitLiteralCompareTypeof(expr, sub_expr, check);
1291    return true;
1292  }
1293
1294  if (expr->IsLiteralCompareUndefined(&sub_expr)) {
1295    EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1296    return true;
1297  }
1298
1299  if (expr->IsLiteralCompareNull(&sub_expr)) {
1300    EmitLiteralCompareNil(expr, sub_expr, kNullValue);
1301    return true;
1302  }
1303
1304  return false;
1305}
1306
1307
1308#undef __
1309
1310
1311} }  // namespace v8::internal
1312