Home | History | Annotate | Download | only in full-codegen
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/full-codegen/full-codegen.h"
      6 
      7 #include "src/ast/ast-numbering.h"
      8 #include "src/ast/ast.h"
      9 #include "src/ast/prettyprinter.h"
     10 #include "src/ast/scopes.h"
     11 #include "src/code-factory.h"
     12 #include "src/codegen.h"
     13 #include "src/compilation-info.h"
     14 #include "src/compiler.h"
     15 #include "src/debug/debug.h"
     16 #include "src/debug/liveedit.h"
     17 #include "src/frames-inl.h"
     18 #include "src/globals.h"
     19 #include "src/isolate-inl.h"
     20 #include "src/macro-assembler.h"
     21 #include "src/snapshot/snapshot.h"
     22 #include "src/tracing/trace-event.h"
     23 
     24 namespace v8 {
     25 namespace internal {
     26 
     27 #define __ ACCESS_MASM(masm())
     28 
     29 class FullCodegenCompilationJob final : public CompilationJob {
     30  public:
     31   explicit FullCodegenCompilationJob(CompilationInfo* info)
     32       : CompilationJob(info->isolate(), info, "Full-Codegen") {}
     33 
     34   bool can_execute_on_background_thread() const override { return false; }
     35 
     36   CompilationJob::Status PrepareJobImpl() final { return SUCCEEDED; }
     37 
     38   CompilationJob::Status ExecuteJobImpl() final {
     39     DCHECK(ThreadId::Current().Equals(isolate()->thread_id()));
     40     return FullCodeGenerator::MakeCode(info(), stack_limit()) ? SUCCEEDED
     41                                                               : FAILED;
     42   }
     43 
     44   CompilationJob::Status FinalizeJobImpl() final { return SUCCEEDED; }
     45 };
     46 
     47 FullCodeGenerator::FullCodeGenerator(MacroAssembler* masm,
     48                                      CompilationInfo* info,
     49                                      uintptr_t stack_limit)
     50     : masm_(masm),
     51       info_(info),
     52       isolate_(info->isolate()),
     53       zone_(info->zone()),
     54       scope_(info->scope()),
     55       nesting_stack_(NULL),
     56       loop_depth_(0),
     57       operand_stack_depth_(0),
     58       globals_(NULL),
     59       context_(NULL),
     60       bailout_entries_(info->HasDeoptimizationSupport()
     61                            ? info->literal()->ast_node_count()
     62                            : 0,
     63                        info->zone()),
     64       back_edges_(2, info->zone()),
     65       handler_table_(info->zone()),
     66       source_position_table_builder_(info->zone(),
     67                                      info->SourcePositionRecordingMode()),
     68       ic_total_count_(0) {
     69   DCHECK(!info->IsStub());
     70   Initialize(stack_limit);
     71 }
     72 
     73 // static
     74 CompilationJob* FullCodeGenerator::NewCompilationJob(CompilationInfo* info) {
     75   return new FullCodegenCompilationJob(info);
     76 }
     77 
     78 // static
     79 bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
     80   return MakeCode(info, info->isolate()->stack_guard()->real_climit());
     81 }
     82 
     83 // static
     84 bool FullCodeGenerator::MakeCode(CompilationInfo* info, uintptr_t stack_limit) {
     85   Isolate* isolate = info->isolate();
     86 
     87   DCHECK(!FLAG_minimal);
     88   RuntimeCallTimerScope runtimeTimer(isolate,
     89                                      &RuntimeCallStats::CompileFullCode);
     90   TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
     91   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileFullCode");
     92 
     93   Handle<Script> script = info->script();
     94   if (!script->IsUndefined(isolate) &&
     95       !script->source()->IsUndefined(isolate)) {
     96     int len = String::cast(script->source())->length();
     97     isolate->counters()->total_full_codegen_source_size()->Increment(len);
     98   }
     99   CodeGenerator::MakeCodePrologue(info, "full");
    100   const int kInitialBufferSize = 4 * KB;
    101   MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize,
    102                       CodeObjectRequired::kYes);
    103   if (info->will_serialize()) masm.enable_serializer();
    104 
    105   FullCodeGenerator cgen(&masm, info, stack_limit);
    106   cgen.Generate();
    107   if (cgen.HasStackOverflow()) {
    108     DCHECK(!isolate->has_pending_exception());
    109     return false;
    110   }
    111   unsigned table_offset = cgen.EmitBackEdgeTable();
    112 
    113   Handle<Code> code =
    114       CodeGenerator::MakeCodeEpilogue(&masm, nullptr, info, masm.CodeObject());
    115   cgen.PopulateDeoptimizationData(code);
    116   cgen.PopulateTypeFeedbackInfo(code);
    117   cgen.PopulateHandlerTable(code);
    118   code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
    119   code->set_has_reloc_info_for_serialization(info->will_serialize());
    120   code->set_allow_osr_at_loop_nesting_level(0);
    121   code->set_profiler_ticks(0);
    122   code->set_back_edge_table_offset(table_offset);
    123   Handle<ByteArray> source_positions =
    124       cgen.source_position_table_builder_.ToSourcePositionTable(
    125           isolate, Handle<AbstractCode>::cast(code));
    126   code->set_source_position_table(*source_positions);
    127   CodeGenerator::PrintCode(code, info);
    128   info->SetCode(code);
    129 
    130 #ifdef DEBUG
    131   // Check that no context-specific object has been embedded.
    132   code->VerifyEmbeddedObjects(Code::kNoContextSpecificPointers);
    133 #endif  // DEBUG
    134   return true;
    135 }
    136 
    137 
    138 unsigned FullCodeGenerator::EmitBackEdgeTable() {
    139   // The back edge table consists of a length (in number of entries)
    140   // field, and then a sequence of entries.  Each entry is a pair of AST id
    141   // and code-relative pc offset.
    142   masm()->Align(kPointerSize);
    143   unsigned offset = masm()->pc_offset();
    144   unsigned length = back_edges_.length();
    145   __ dd(length);
    146   for (unsigned i = 0; i < length; ++i) {
    147     __ dd(back_edges_[i].id.ToInt());
    148     __ dd(back_edges_[i].pc);
    149     __ dd(back_edges_[i].loop_depth);
    150   }
    151   return offset;
    152 }
    153 
    154 
    155 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
    156   // Fill in the deoptimization information.
    157   DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
    158   if (!info_->HasDeoptimizationSupport()) return;
    159   int length = bailout_entries_.length();
    160   Handle<DeoptimizationOutputData> data =
    161       DeoptimizationOutputData::New(isolate(), length, TENURED);
    162   for (int i = 0; i < length; i++) {
    163     data->SetAstId(i, bailout_entries_[i].id);
    164     data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
    165   }
    166   code->set_deoptimization_data(*data);
    167 }
    168 
    169 
    170 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
    171   Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
    172   info->set_ic_total_count(ic_total_count_);
    173   DCHECK(!isolate()->heap()->InNewSpace(*info));
    174   code->set_type_feedback_info(*info);
    175 }
    176 
    177 
    178 void FullCodeGenerator::PopulateHandlerTable(Handle<Code> code) {
    179   int handler_table_size = static_cast<int>(handler_table_.size());
    180   Handle<HandlerTable> table =
    181       Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
    182           HandlerTable::LengthForRange(handler_table_size), TENURED));
    183   for (int i = 0; i < handler_table_size; ++i) {
    184     table->SetRangeStart(i, handler_table_[i].range_start);
    185     table->SetRangeEnd(i, handler_table_[i].range_end);
    186     table->SetRangeHandler(i, handler_table_[i].handler_offset,
    187                            handler_table_[i].catch_prediction);
    188     table->SetRangeData(i, handler_table_[i].stack_depth);
    189   }
    190   code->set_handler_table(*table);
    191 }
    192 
    193 
    194 int FullCodeGenerator::NewHandlerTableEntry() {
    195   int index = static_cast<int>(handler_table_.size());
    196   HandlerTableEntry entry = {0, 0, 0, 0, HandlerTable::UNCAUGHT};
    197   handler_table_.push_back(entry);
    198   return index;
    199 }
    200 
    201 
    202 bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
    203     ObjectLiteral* expr) const {
    204   return masm()->serializer_enabled() ||
    205          !FastCloneShallowObjectStub::IsSupported(expr);
    206 }
    207 
    208 
    209 bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
    210     ArrayLiteral* expr) const {
    211   return expr->depth() > 1 ||
    212          expr->values()->length() > JSArray::kInitialMaxFastElementArray;
    213 }
    214 
    215 void FullCodeGenerator::Initialize(uintptr_t stack_limit) {
    216   InitializeAstVisitor(stack_limit);
    217   masm_->set_emit_debug_code(FLAG_debug_code);
    218   masm_->set_predictable_code_size(true);
    219 }
    220 
    221 void FullCodeGenerator::PrepareForBailout(Expression* node,
    222                                           BailoutState state) {
    223   PrepareForBailoutForId(node->id(), state);
    224 }
    225 
    226 void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
    227   ic_total_count_++;
    228   __ Call(code, RelocInfo::CODE_TARGET, ast_id);
    229 }
    230 
    231 void FullCodeGenerator::CallLoadIC(FeedbackVectorSlot slot,
    232                                    Handle<Object> name) {
    233   DCHECK(name->IsName());
    234   __ Move(LoadDescriptor::NameRegister(), name);
    235 
    236   EmitLoadSlot(LoadDescriptor::SlotRegister(), slot);
    237 
    238   Handle<Code> code = CodeFactory::LoadIC(isolate()).code();
    239   __ Call(code, RelocInfo::CODE_TARGET);
    240   if (FLAG_tf_load_ic_stub) RestoreContext();
    241 }
    242 
    243 void FullCodeGenerator::CallStoreIC(FeedbackVectorSlot slot,
    244                                     Handle<Object> name) {
    245   DCHECK(name->IsName());
    246   __ Move(StoreDescriptor::NameRegister(), name);
    247 
    248   STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
    249                 StoreDescriptor::kStackArgumentsCount == 2);
    250   if (StoreDescriptor::kPassLastArgsOnStack) {
    251     __ Push(StoreDescriptor::ValueRegister());
    252     EmitPushSlot(slot);
    253   } else {
    254     EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
    255   }
    256 
    257   Handle<Code> code = CodeFactory::StoreIC(isolate(), language_mode()).code();
    258   __ Call(code, RelocInfo::CODE_TARGET);
    259   RestoreContext();
    260 }
    261 
    262 void FullCodeGenerator::CallKeyedStoreIC(FeedbackVectorSlot slot) {
    263   STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
    264                 StoreDescriptor::kStackArgumentsCount == 2);
    265   if (StoreDescriptor::kPassLastArgsOnStack) {
    266     __ Push(StoreDescriptor::ValueRegister());
    267     EmitPushSlot(slot);
    268   } else {
    269     EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
    270   }
    271 
    272   Handle<Code> code =
    273       CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
    274   __ Call(code, RelocInfo::CODE_TARGET);
    275   RestoreContext();
    276 }
    277 
    278 void FullCodeGenerator::RecordJSReturnSite(Call* call) {
    279   // We record the offset of the function return so we can rebuild the frame
    280   // if the function was inlined, i.e., this is the return address in the
    281   // inlined function's frame.
    282   //
    283   // The bailout state is ignored.  We defensively set it to TOS_REGISTER, which
    284   // is the real state of the unoptimized code at the return site.
    285   PrepareForBailoutForId(call->ReturnId(), BailoutState::TOS_REGISTER);
    286 #ifdef DEBUG
    287   // In debug builds, mark the return so we can verify that this function
    288   // was called.
    289   DCHECK(!call->return_is_recorded_);
    290   call->return_is_recorded_ = true;
    291 #endif
    292 }
    293 
    294 void FullCodeGenerator::PrepareForBailoutForId(BailoutId id,
    295                                                BailoutState state) {
    296   // There's no need to prepare this code for bailouts from already optimized
    297   // code or code that can't be optimized.
    298   if (!info_->HasDeoptimizationSupport()) return;
    299   unsigned pc_and_state =
    300       BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
    301   DCHECK(Smi::IsValid(pc_and_state));
    302 #ifdef DEBUG
    303   for (int i = 0; i < bailout_entries_.length(); ++i) {
    304     DCHECK(bailout_entries_[i].id != id);
    305   }
    306 #endif
    307   BailoutEntry entry = { id, pc_and_state };
    308   bailout_entries_.Add(entry, zone());
    309 }
    310 
    311 
    312 void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
    313   // The pc offset does not need to be encoded and packed together with a state.
    314   DCHECK(masm_->pc_offset() > 0);
    315   DCHECK(loop_depth() > 0);
    316   uint8_t depth = Min(loop_depth(), AbstractCode::kMaxLoopNestingMarker);
    317   BackEdgeEntry entry =
    318       { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
    319   back_edges_.Add(entry, zone());
    320 }
    321 
    322 
    323 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
    324   // Inline smi case inside loops, but not division and modulo which
    325   // are too complicated and take up too much space.
    326   if (op == Token::DIV ||op == Token::MOD) return false;
    327   if (FLAG_always_inline_smi_code) return true;
    328   return loop_depth_ > 0;
    329 }
    330 
    331 
    332 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
    333   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
    334 }
    335 
    336 
    337 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
    338   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
    339   codegen()->GetVar(result_register(), var);
    340 }
    341 
    342 
    343 void FullCodeGenerator::TestContext::Plug(Variable* var) const {
    344   DCHECK(var->IsStackAllocated() || var->IsContextSlot());
    345   // For simplicity we always test the accumulator register.
    346   codegen()->GetVar(result_register(), var);
    347   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    348   codegen()->DoTest(this);
    349 }
    350 
    351 
    352 void FullCodeGenerator::EffectContext::Plug(Register reg) const {
    353 }
    354 
    355 
    356 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
    357   __ Move(result_register(), reg);
    358 }
    359 
    360 
    361 void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
    362   codegen()->PushOperand(reg);
    363 }
    364 
    365 
    366 void FullCodeGenerator::TestContext::Plug(Register reg) const {
    367   // For simplicity we always test the accumulator register.
    368   __ Move(result_register(), reg);
    369   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    370   codegen()->DoTest(this);
    371 }
    372 
    373 
    374 void FullCodeGenerator::EffectContext::Plug(bool flag) const {}
    375 
    376 void FullCodeGenerator::EffectContext::DropAndPlug(int count,
    377                                                    Register reg) const {
    378   DCHECK(count > 0);
    379   codegen()->DropOperands(count);
    380 }
    381 
    382 void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
    383     int count, Register reg) const {
    384   DCHECK(count > 0);
    385   codegen()->DropOperands(count);
    386   __ Move(result_register(), reg);
    387 }
    388 
    389 void FullCodeGenerator::TestContext::DropAndPlug(int count,
    390                                                  Register reg) const {
    391   DCHECK(count > 0);
    392   // For simplicity we always test the accumulator register.
    393   codegen()->DropOperands(count);
    394   __ Move(result_register(), reg);
    395   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    396   codegen()->DoTest(this);
    397 }
    398 
    399 void FullCodeGenerator::EffectContext::PlugTOS() const {
    400   codegen()->DropOperands(1);
    401 }
    402 
    403 
    404 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
    405   codegen()->PopOperand(result_register());
    406 }
    407 
    408 
    409 void FullCodeGenerator::StackValueContext::PlugTOS() const {
    410 }
    411 
    412 
    413 void FullCodeGenerator::TestContext::PlugTOS() const {
    414   // For simplicity we always test the accumulator register.
    415   codegen()->PopOperand(result_register());
    416   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
    417   codegen()->DoTest(this);
    418 }
    419 
    420 
    421 void FullCodeGenerator::EffectContext::PrepareTest(
    422     Label* materialize_true,
    423     Label* materialize_false,
    424     Label** if_true,
    425     Label** if_false,
    426     Label** fall_through) const {
    427   // In an effect context, the true and the false case branch to the
    428   // same label.
    429   *if_true = *if_false = *fall_through = materialize_true;
    430 }
    431 
    432 
    433 void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
    434     Label* materialize_true,
    435     Label* materialize_false,
    436     Label** if_true,
    437     Label** if_false,
    438     Label** fall_through) const {
    439   *if_true = *fall_through = materialize_true;
    440   *if_false = materialize_false;
    441 }
    442 
    443 
    444 void FullCodeGenerator::StackValueContext::PrepareTest(
    445     Label* materialize_true,
    446     Label* materialize_false,
    447     Label** if_true,
    448     Label** if_false,
    449     Label** fall_through) const {
    450   *if_true = *fall_through = materialize_true;
    451   *if_false = materialize_false;
    452 }
    453 
    454 
    455 void FullCodeGenerator::TestContext::PrepareTest(
    456     Label* materialize_true,
    457     Label* materialize_false,
    458     Label** if_true,
    459     Label** if_false,
    460     Label** fall_through) const {
    461   *if_true = true_label_;
    462   *if_false = false_label_;
    463   *fall_through = fall_through_;
    464 }
    465 
    466 
    467 void FullCodeGenerator::DoTest(const TestContext* context) {
    468   DoTest(context->condition(),
    469          context->true_label(),
    470          context->false_label(),
    471          context->fall_through());
    472 }
    473 
    474 void FullCodeGenerator::VisitDeclarations(Declaration::List* declarations) {
    475   ZoneList<Handle<Object> >* saved_globals = globals_;
    476   ZoneList<Handle<Object> > inner_globals(10, zone());
    477   globals_ = &inner_globals;
    478 
    479   AstVisitor<FullCodeGenerator>::VisitDeclarations(declarations);
    480 
    481   if (!globals_->is_empty()) {
    482     // Invoke the platform-dependent code generator to do the actual
    483     // declaration of the global functions and variables.
    484     Handle<FixedArray> array =
    485        isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
    486     for (int i = 0; i < globals_->length(); ++i)
    487       array->set(i, *globals_->at(i));
    488     DeclareGlobals(array);
    489   }
    490 
    491   globals_ = saved_globals;
    492 }
    493 
    494 
    495 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
    496   Comment cmnt(masm_, "[ VariableProxy");
    497   EmitVariableLoad(expr);
    498 }
    499 
    500 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
    501                                                TypeofMode typeof_mode) {
    502 #ifdef DEBUG
    503   Variable* var = proxy->var();
    504   DCHECK(var->IsUnallocated() ||
    505          (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
    506 #endif
    507   EmitLoadSlot(LoadGlobalDescriptor::SlotRegister(),
    508                proxy->VariableFeedbackSlot());
    509   Handle<Code> code = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
    510   __ Call(code, RelocInfo::CODE_TARGET);
    511 }
    512 
    513 void FullCodeGenerator::VisitSloppyBlockFunctionStatement(
    514     SloppyBlockFunctionStatement* declaration) {
    515   Visit(declaration->statement());
    516 }
    517 
    518 
    519 int FullCodeGenerator::DeclareGlobalsFlags() {
    520   return info_->GetDeclareGlobalsFlags();
    521 }
    522 
    523 void FullCodeGenerator::PushOperand(Handle<Object> handle) {
    524   OperandStackDepthIncrement(1);
    525   __ Push(handle);
    526 }
    527 
    528 void FullCodeGenerator::PushOperand(Smi* smi) {
    529   OperandStackDepthIncrement(1);
    530   __ Push(smi);
    531 }
    532 
    533 void FullCodeGenerator::PushOperand(Register reg) {
    534   OperandStackDepthIncrement(1);
    535   __ Push(reg);
    536 }
    537 
    538 void FullCodeGenerator::PopOperand(Register reg) {
    539   OperandStackDepthDecrement(1);
    540   __ Pop(reg);
    541 }
    542 
    543 void FullCodeGenerator::DropOperands(int count) {
    544   OperandStackDepthDecrement(count);
    545   __ Drop(count);
    546 }
    547 
    548 void FullCodeGenerator::CallRuntimeWithOperands(Runtime::FunctionId id) {
    549   OperandStackDepthDecrement(Runtime::FunctionForId(id)->nargs);
    550   __ CallRuntime(id);
    551 }
    552 
    553 void FullCodeGenerator::OperandStackDepthIncrement(int count) {
    554   DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= 0);
    555   DCHECK_GE(count, 0);
    556   operand_stack_depth_ += count;
    557 }
    558 
    559 void FullCodeGenerator::OperandStackDepthDecrement(int count) {
    560   DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= count);
    561   DCHECK_GE(count, 0);
    562   operand_stack_depth_ -= count;
    563 }
    564 
    565 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
    566   // Load the arguments on the stack and call the stub.
    567   SubStringStub stub(isolate());
    568   ZoneList<Expression*>* args = expr->arguments();
    569   DCHECK(args->length() == 3);
    570   VisitForStackValue(args->at(0));
    571   VisitForStackValue(args->at(1));
    572   VisitForStackValue(args->at(2));
    573   __ CallStub(&stub);
    574   RestoreContext();
    575   OperandStackDepthDecrement(3);
    576   context()->Plug(result_register());
    577 }
    578 
    579 
    580 void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
    581   // Load the arguments on the stack and call the stub.
    582   RegExpExecStub stub(isolate());
    583   ZoneList<Expression*>* args = expr->arguments();
    584   DCHECK(args->length() == 4);
    585   VisitForStackValue(args->at(0));
    586   VisitForStackValue(args->at(1));
    587   VisitForStackValue(args->at(2));
    588   VisitForStackValue(args->at(3));
    589   __ CallStub(&stub);
    590   OperandStackDepthDecrement(4);
    591   context()->Plug(result_register());
    592 }
    593 
    594 
    595 void FullCodeGenerator::EmitIntrinsicAsStubCall(CallRuntime* expr,
    596                                                 const Callable& callable) {
    597   ZoneList<Expression*>* args = expr->arguments();
    598   int param_count = callable.descriptor().GetRegisterParameterCount();
    599   DCHECK_EQ(args->length(), param_count);
    600 
    601   if (param_count > 0) {
    602     int last = param_count - 1;
    603     // Put all but last arguments on stack.
    604     for (int i = 0; i < last; i++) {
    605       VisitForStackValue(args->at(i));
    606     }
    607     // The last argument goes to the accumulator.
    608     VisitForAccumulatorValue(args->at(last));
    609 
    610     // Move the arguments to the registers, as required by the stub.
    611     __ Move(callable.descriptor().GetRegisterParameter(last),
    612             result_register());
    613     for (int i = last; i-- > 0;) {
    614       PopOperand(callable.descriptor().GetRegisterParameter(i));
    615     }
    616   }
    617   __ Call(callable.code(), RelocInfo::CODE_TARGET);
    618 
    619   // Reload the context register after the call as i.e. TurboFan code stubs
    620   // won't preserve the context register.
    621   LoadFromFrameField(StandardFrameConstants::kContextOffset,
    622                      context_register());
    623   context()->Plug(result_register());
    624 }
    625 
    626 void FullCodeGenerator::EmitNewObject(CallRuntime* expr) {
    627   EmitIntrinsicAsStubCall(expr, CodeFactory::FastNewObject(isolate()));
    628 }
    629 
    630 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
    631   EmitIntrinsicAsStubCall(expr, CodeFactory::NumberToString(isolate()));
    632 }
    633 
    634 
    635 void FullCodeGenerator::EmitToString(CallRuntime* expr) {
    636   EmitIntrinsicAsStubCall(expr, CodeFactory::ToString(isolate()));
    637 }
    638 
    639 
    640 void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
    641   EmitIntrinsicAsStubCall(expr, CodeFactory::ToLength(isolate()));
    642 }
    643 
    644 void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
    645   EmitIntrinsicAsStubCall(expr, CodeFactory::ToInteger(isolate()));
    646 }
    647 
    648 void FullCodeGenerator::EmitToNumber(CallRuntime* expr) {
    649   EmitIntrinsicAsStubCall(expr, CodeFactory::ToNumber(isolate()));
    650 }
    651 
    652 
    653 void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
    654   EmitIntrinsicAsStubCall(expr, CodeFactory::ToObject(isolate()));
    655 }
    656 
    657 
    658 void FullCodeGenerator::EmitHasProperty() {
    659   Callable callable = CodeFactory::HasProperty(isolate());
    660   PopOperand(callable.descriptor().GetRegisterParameter(1));
    661   PopOperand(callable.descriptor().GetRegisterParameter(0));
    662   __ Call(callable.code(), RelocInfo::CODE_TARGET);
    663   RestoreContext();
    664 }
    665 
    666 void FullCodeGenerator::RecordStatementPosition(int pos) {
    667   DCHECK_NE(kNoSourcePosition, pos);
    668   source_position_table_builder_.AddPosition(masm_->pc_offset(),
    669                                              SourcePosition(pos), true);
    670 }
    671 
    672 void FullCodeGenerator::RecordPosition(int pos) {
    673   DCHECK_NE(kNoSourcePosition, pos);
    674   source_position_table_builder_.AddPosition(masm_->pc_offset(),
    675                                              SourcePosition(pos), false);
    676 }
    677 
    678 
    679 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
    680   RecordPosition(fun->start_position());
    681 }
    682 
    683 
    684 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
    685   // For default constructors, start position equals end position, and there
    686   // is no source code besides the class literal.
    687   RecordStatementPosition(fun->return_position());
    688   if (info_->is_debug()) {
    689     // Always emit a debug break slot before a return.
    690     DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
    691   }
    692 }
    693 
    694 
    695 void FullCodeGenerator::SetStatementPosition(
    696     Statement* stmt, FullCodeGenerator::InsertBreak insert_break) {
    697   if (stmt->position() == kNoSourcePosition) return;
    698   RecordStatementPosition(stmt->position());
    699   if (insert_break == INSERT_BREAK && info_->is_debug() &&
    700       !stmt->IsDebuggerStatement()) {
    701     DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
    702   }
    703 }
    704 
    705 void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
    706   if (expr->position() == kNoSourcePosition) return;
    707   RecordPosition(expr->position());
    708 }
    709 
    710 
    711 void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
    712   if (expr->position() == kNoSourcePosition) return;
    713   RecordStatementPosition(expr->position());
    714   if (info_->is_debug()) {
    715     DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
    716   }
    717 }
    718 
    719 void FullCodeGenerator::SetCallPosition(Expression* expr,
    720                                         TailCallMode tail_call_mode) {
    721   if (expr->position() == kNoSourcePosition) return;
    722   RecordPosition(expr->position());
    723   if (info_->is_debug()) {
    724     RelocInfo::Mode mode = (tail_call_mode == TailCallMode::kAllow)
    725                                ? RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL
    726                                : RelocInfo::DEBUG_BREAK_SLOT_AT_CALL;
    727     // Always emit a debug break slot before a call.
    728     DebugCodegen::GenerateSlot(masm_, mode);
    729   }
    730 }
    731 
    732 
    733 void FullCodeGenerator::VisitSuperPropertyReference(
    734     SuperPropertyReference* super) {
    735   __ CallRuntime(Runtime::kThrowUnsupportedSuperError);
    736   // Even though this expression doesn't produce a value, we need to simulate
    737   // plugging of the value context to ensure stack depth tracking is in sync.
    738   if (context()->IsStackValue()) OperandStackDepthIncrement(1);
    739 }
    740 
    741 
    742 void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
    743   // Handled by VisitCall
    744   UNREACHABLE();
    745 }
    746 
    747 
    748 void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
    749   context()->Plug(handle(Smi::kZero, isolate()));
    750 }
    751 
    752 
    753 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
    754   switch (expr->op()) {
    755     case Token::COMMA:
    756       return VisitComma(expr);
    757     case Token::OR:
    758     case Token::AND:
    759       return VisitLogicalExpression(expr);
    760     default:
    761       return VisitArithmeticExpression(expr);
    762   }
    763 }
    764 
    765 
    766 void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
    767   if (context()->IsEffect()) {
    768     VisitForEffect(expr);
    769   } else if (context()->IsAccumulatorValue()) {
    770     VisitForAccumulatorValue(expr);
    771   } else if (context()->IsStackValue()) {
    772     VisitForStackValue(expr);
    773   } else if (context()->IsTest()) {
    774     const TestContext* test = TestContext::cast(context());
    775     VisitForControl(expr, test->true_label(), test->false_label(),
    776                     test->fall_through());
    777   }
    778 }
    779 
    780 
    781 void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
    782   Comment cmnt(masm_, "[ Comma");
    783   VisitForEffect(expr->left());
    784   VisitInDuplicateContext(expr->right());
    785 }
    786 
    787 
    788 void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
    789   bool is_logical_and = expr->op() == Token::AND;
    790   Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
    791   Expression* left = expr->left();
    792   Expression* right = expr->right();
    793   BailoutId right_id = expr->RightId();
    794   Label done;
    795 
    796   if (context()->IsTest()) {
    797     Label eval_right;
    798     const TestContext* test = TestContext::cast(context());
    799     if (is_logical_and) {
    800       VisitForControl(left, &eval_right, test->false_label(), &eval_right);
    801     } else {
    802       VisitForControl(left, test->true_label(), &eval_right, &eval_right);
    803     }
    804     PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    805     __ bind(&eval_right);
    806 
    807   } else if (context()->IsAccumulatorValue()) {
    808     VisitForAccumulatorValue(left);
    809     // We want the value in the accumulator for the test, and on the stack in
    810     // case we need it.
    811     __ Push(result_register());
    812     Label discard, restore;
    813     if (is_logical_and) {
    814       DoTest(left, &discard, &restore, &restore);
    815     } else {
    816       DoTest(left, &restore, &discard, &restore);
    817     }
    818     __ bind(&restore);
    819     __ Pop(result_register());
    820     __ jmp(&done);
    821     __ bind(&discard);
    822     __ Drop(1);
    823     PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    824 
    825   } else if (context()->IsStackValue()) {
    826     VisitForAccumulatorValue(left);
    827     // We want the value in the accumulator for the test, and on the stack in
    828     // case we need it.
    829     __ Push(result_register());
    830     Label discard;
    831     if (is_logical_and) {
    832       DoTest(left, &discard, &done, &discard);
    833     } else {
    834       DoTest(left, &done, &discard, &discard);
    835     }
    836     __ bind(&discard);
    837     __ Drop(1);
    838     PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    839 
    840   } else {
    841     DCHECK(context()->IsEffect());
    842     Label eval_right;
    843     if (is_logical_and) {
    844       VisitForControl(left, &eval_right, &done, &eval_right);
    845     } else {
    846       VisitForControl(left, &done, &eval_right, &eval_right);
    847     }
    848     PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
    849     __ bind(&eval_right);
    850   }
    851 
    852   VisitInDuplicateContext(right);
    853   __ bind(&done);
    854 }
    855 
    856 
    857 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
    858   Token::Value op = expr->op();
    859   Comment cmnt(masm_, "[ ArithmeticExpression");
    860   Expression* left = expr->left();
    861   Expression* right = expr->right();
    862 
    863   VisitForStackValue(left);
    864   VisitForAccumulatorValue(right);
    865 
    866   SetExpressionPosition(expr);
    867   if (ShouldInlineSmiCase(op)) {
    868     EmitInlineSmiBinaryOp(expr, op, left, right);
    869   } else {
    870     EmitBinaryOp(expr, op);
    871   }
    872 }
    873 
    874 void FullCodeGenerator::VisitProperty(Property* expr) {
    875   Comment cmnt(masm_, "[ Property");
    876   SetExpressionPosition(expr);
    877 
    878   Expression* key = expr->key();
    879 
    880   if (key->IsPropertyName()) {
    881     if (!expr->IsSuperAccess()) {
    882       VisitForAccumulatorValue(expr->obj());
    883       __ Move(LoadDescriptor::ReceiverRegister(), result_register());
    884       EmitNamedPropertyLoad(expr);
    885     } else {
    886       VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
    887       VisitForStackValue(
    888           expr->obj()->AsSuperPropertyReference()->home_object());
    889       EmitNamedSuperPropertyLoad(expr);
    890     }
    891   } else {
    892     if (!expr->IsSuperAccess()) {
    893       VisitForStackValue(expr->obj());
    894       VisitForAccumulatorValue(expr->key());
    895       __ Move(LoadDescriptor::NameRegister(), result_register());
    896       PopOperand(LoadDescriptor::ReceiverRegister());
    897       EmitKeyedPropertyLoad(expr);
    898     } else {
    899       VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var());
    900       VisitForStackValue(
    901           expr->obj()->AsSuperPropertyReference()->home_object());
    902       VisitForStackValue(expr->key());
    903       EmitKeyedSuperPropertyLoad(expr);
    904     }
    905   }
    906   PrepareForBailoutForId(expr->LoadId(), BailoutState::TOS_REGISTER);
    907   context()->Plug(result_register());
    908 }
    909 
    910 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
    911   VariableProxy* proxy = expr->AsVariableProxy();
    912   DCHECK(!context()->IsEffect());
    913   DCHECK(!context()->IsTest());
    914 
    915   if (proxy != NULL &&
    916       (proxy->var()->IsUnallocated() || proxy->var()->IsLookupSlot())) {
    917     EmitVariableLoad(proxy, INSIDE_TYPEOF);
    918     PrepareForBailout(proxy, BailoutState::TOS_REGISTER);
    919   } else {
    920     // This expression cannot throw a reference error at the top level.
    921     VisitInDuplicateContext(expr);
    922   }
    923 }
    924 
    925 
    926 void FullCodeGenerator::VisitBlock(Block* stmt) {
    927   Comment cmnt(masm_, "[ Block");
    928   NestedBlock nested_block(this, stmt);
    929 
    930   {
    931     EnterBlockScopeIfNeeded block_scope_state(
    932         this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId());
    933     VisitStatements(stmt->statements());
    934     __ bind(nested_block.break_label());
    935   }
    936 }
    937 
    938 
    939 void FullCodeGenerator::VisitDoExpression(DoExpression* expr) {
    940   Comment cmnt(masm_, "[ Do Expression");
    941   SetExpressionPosition(expr);
    942   VisitBlock(expr->block());
    943   VisitInDuplicateContext(expr->result());
    944 }
    945 
    946 
    947 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
    948   Comment cmnt(masm_, "[ ExpressionStatement");
    949   SetStatementPosition(stmt);
    950   VisitForEffect(stmt->expression());
    951 }
    952 
    953 
    954 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
    955   Comment cmnt(masm_, "[ EmptyStatement");
    956 }
    957 
    958 
    959 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
    960   Comment cmnt(masm_, "[ IfStatement");
    961   SetStatementPosition(stmt);
    962   Label then_part, else_part, done;
    963 
    964   if (stmt->HasElseStatement()) {
    965     VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
    966     PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
    967     __ bind(&then_part);
    968     Visit(stmt->then_statement());
    969     __ jmp(&done);
    970 
    971     PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
    972     __ bind(&else_part);
    973     Visit(stmt->else_statement());
    974   } else {
    975     VisitForControl(stmt->condition(), &then_part, &done, &then_part);
    976     PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
    977     __ bind(&then_part);
    978     Visit(stmt->then_statement());
    979 
    980     PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
    981   }
    982   __ bind(&done);
    983   PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS);
    984 }
    985 
    986 void FullCodeGenerator::EmitContinue(Statement* target) {
    987   NestedStatement* current = nesting_stack_;
    988   int context_length = 0;
    989   // When continuing, we clobber the unpredictable value in the accumulator
    990   // with one that's safe for GC.  If we hit an exit from the try block of
    991   // try...finally on our way out, we will unconditionally preserve the
    992   // accumulator on the stack.
    993   ClearAccumulator();
    994   while (!current->IsContinueTarget(target)) {
    995     if (HasStackOverflow()) return;
    996     if (current->IsTryFinally()) {
    997       Comment cmnt(masm(), "[ Deferred continue through finally");
    998       current->Exit(&context_length);
    999       DCHECK_EQ(-1, context_length);
   1000       current->AsTryFinally()->deferred_commands()->RecordContinue(target);
   1001       return;
   1002     }
   1003     current = current->Exit(&context_length);
   1004   }
   1005   int stack_depth = current->GetStackDepthAtTarget();
   1006   int stack_drop = operand_stack_depth_ - stack_depth;
   1007   DCHECK_GE(stack_drop, 0);
   1008   __ Drop(stack_drop);
   1009   if (context_length > 0) {
   1010     while (context_length > 0) {
   1011       LoadContextField(context_register(), Context::PREVIOUS_INDEX);
   1012       --context_length;
   1013     }
   1014     StoreToFrameField(StandardFrameConstants::kContextOffset,
   1015                       context_register());
   1016   }
   1017 
   1018   __ jmp(current->AsIteration()->continue_label());
   1019 }
   1020 
   1021 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
   1022   Comment cmnt(masm_, "[ ContinueStatement");
   1023   SetStatementPosition(stmt);
   1024   EmitContinue(stmt->target());
   1025 }
   1026 
   1027 void FullCodeGenerator::EmitBreak(Statement* target) {
   1028   NestedStatement* current = nesting_stack_;
   1029   int context_length = 0;
   1030   // When breaking, we clobber the unpredictable value in the accumulator
   1031   // with one that's safe for GC.  If we hit an exit from the try block of
   1032   // try...finally on our way out, we will unconditionally preserve the
   1033   // accumulator on the stack.
   1034   ClearAccumulator();
   1035   while (!current->IsBreakTarget(target)) {
   1036     if (HasStackOverflow()) return;
   1037     if (current->IsTryFinally()) {
   1038       Comment cmnt(masm(), "[ Deferred break through finally");
   1039       current->Exit(&context_length);
   1040       DCHECK_EQ(-1, context_length);
   1041       current->AsTryFinally()->deferred_commands()->RecordBreak(target);
   1042       return;
   1043     }
   1044     current = current->Exit(&context_length);
   1045   }
   1046   int stack_depth = current->GetStackDepthAtTarget();
   1047   int stack_drop = operand_stack_depth_ - stack_depth;
   1048   DCHECK_GE(stack_drop, 0);
   1049   __ Drop(stack_drop);
   1050   if (context_length > 0) {
   1051     while (context_length > 0) {
   1052       LoadContextField(context_register(), Context::PREVIOUS_INDEX);
   1053       --context_length;
   1054     }
   1055     StoreToFrameField(StandardFrameConstants::kContextOffset,
   1056                       context_register());
   1057   }
   1058 
   1059   __ jmp(current->AsBreakable()->break_label());
   1060 }
   1061 
   1062 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
   1063   Comment cmnt(masm_, "[ BreakStatement");
   1064   SetStatementPosition(stmt);
   1065   EmitBreak(stmt->target());
   1066 }
   1067 
   1068 void FullCodeGenerator::EmitUnwindAndReturn() {
   1069   NestedStatement* current = nesting_stack_;
   1070   int context_length = 0;
   1071   while (current != NULL) {
   1072     if (HasStackOverflow()) return;
   1073     if (current->IsTryFinally()) {
   1074       Comment cmnt(masm(), "[ Deferred return through finally");
   1075       current->Exit(&context_length);
   1076       DCHECK_EQ(-1, context_length);
   1077       current->AsTryFinally()->deferred_commands()->RecordReturn();
   1078       return;
   1079     }
   1080     current = current->Exit(&context_length);
   1081   }
   1082   EmitReturnSequence();
   1083 }
   1084 
   1085 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
   1086                                        bool pretenure) {
   1087   // If we're running with the --always-opt or the --prepare-always-opt
   1088   // flag, we need to use the runtime function so that the new function
   1089   // we are creating here gets a chance to have its code optimized and
   1090   // doesn't just get a copy of the existing unoptimized code.
   1091   if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure &&
   1092       scope()->is_function_scope()) {
   1093     FastNewClosureStub stub(isolate());
   1094     __ Move(stub.GetCallInterfaceDescriptor().GetRegisterParameter(0), info);
   1095     __ CallStub(&stub);
   1096   } else {
   1097     __ Push(info);
   1098     __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured
   1099                              : Runtime::kNewClosure);
   1100   }
   1101   context()->Plug(result_register());
   1102 }
   1103 
   1104 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   1105   SetExpressionPosition(prop);
   1106   Literal* key = prop->key()->AsLiteral();
   1107   DCHECK(!key->value()->IsSmi());
   1108   DCHECK(!prop->IsSuperAccess());
   1109 
   1110   CallLoadIC(prop->PropertyFeedbackSlot(), key->value());
   1111 }
   1112 
   1113 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
   1114   // Stack: receiver, home_object
   1115   SetExpressionPosition(prop);
   1116   Literal* key = prop->key()->AsLiteral();
   1117   DCHECK(!key->value()->IsSmi());
   1118   DCHECK(prop->IsSuperAccess());
   1119 
   1120   PushOperand(key->value());
   1121   CallRuntimeWithOperands(Runtime::kLoadFromSuper);
   1122 }
   1123 
   1124 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   1125   SetExpressionPosition(prop);
   1126 
   1127   EmitLoadSlot(LoadDescriptor::SlotRegister(), prop->PropertyFeedbackSlot());
   1128 
   1129   Handle<Code> code = CodeFactory::KeyedLoadIC(isolate()).code();
   1130   __ Call(code, RelocInfo::CODE_TARGET);
   1131   RestoreContext();
   1132 }
   1133 
   1134 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
   1135   // Stack: receiver, home_object, key.
   1136   SetExpressionPosition(prop);
   1137   CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
   1138 }
   1139 
   1140 void FullCodeGenerator::EmitPropertyKey(LiteralProperty* property,
   1141                                         BailoutId bailout_id) {
   1142   VisitForStackValue(property->key());
   1143   CallRuntimeWithOperands(Runtime::kToName);
   1144   PrepareForBailoutForId(bailout_id, BailoutState::TOS_REGISTER);
   1145   PushOperand(result_register());
   1146 }
   1147 
   1148 void FullCodeGenerator::EmitLoadSlot(Register destination,
   1149                                      FeedbackVectorSlot slot) {
   1150   DCHECK(!slot.IsInvalid());
   1151   __ Move(destination, SmiFromSlot(slot));
   1152 }
   1153 
   1154 void FullCodeGenerator::EmitPushSlot(FeedbackVectorSlot slot) {
   1155   __ Push(SmiFromSlot(slot));
   1156 }
   1157 
   1158 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
   1159   Comment cmnt(masm_, "[ ReturnStatement");
   1160   SetStatementPosition(stmt);
   1161   Expression* expr = stmt->expression();
   1162   VisitForAccumulatorValue(expr);
   1163   EmitUnwindAndReturn();
   1164 }
   1165 
   1166 
   1167 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
   1168   Comment cmnt(masm_, "[ WithStatement");
   1169   SetStatementPosition(stmt);
   1170 
   1171   VisitForAccumulatorValue(stmt->expression());
   1172   Callable callable = CodeFactory::ToObject(isolate());
   1173   __ Move(callable.descriptor().GetRegisterParameter(0), result_register());
   1174   __ Call(callable.code(), RelocInfo::CODE_TARGET);
   1175   RestoreContext();
   1176   PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
   1177   PushOperand(result_register());
   1178   PushOperand(stmt->scope()->scope_info());
   1179   PushFunctionArgumentForContextAllocation();
   1180   CallRuntimeWithOperands(Runtime::kPushWithContext);
   1181   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
   1182   PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
   1183 
   1184   Scope* saved_scope = scope();
   1185   scope_ = stmt->scope();
   1186   { WithOrCatch body(this);
   1187     Visit(stmt->statement());
   1188   }
   1189   scope_ = saved_scope;
   1190 
   1191   // Pop context.
   1192   LoadContextField(context_register(), Context::PREVIOUS_INDEX);
   1193   // Update local stack frame context field.
   1194   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
   1195 }
   1196 
   1197 
   1198 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
   1199   Comment cmnt(masm_, "[ DoWhileStatement");
   1200   // Do not insert break location as we do that below.
   1201   SetStatementPosition(stmt, SKIP_BREAK);
   1202 
   1203   Label body, book_keeping;
   1204 
   1205   Iteration loop_statement(this, stmt);
   1206   increment_loop_depth();
   1207 
   1208   __ bind(&body);
   1209   Visit(stmt->body());
   1210 
   1211   // Record the position of the do while condition and make sure it is
   1212   // possible to break on the condition.
   1213   __ bind(loop_statement.continue_label());
   1214   PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
   1215 
   1216   // Here is the actual 'while' keyword.
   1217   SetExpressionAsStatementPosition(stmt->cond());
   1218   VisitForControl(stmt->cond(),
   1219                   &book_keeping,
   1220                   loop_statement.break_label(),
   1221                   &book_keeping);
   1222 
   1223   // Check stack before looping.
   1224   PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
   1225   __ bind(&book_keeping);
   1226   EmitBackEdgeBookkeeping(stmt, &body);
   1227   __ jmp(&body);
   1228 
   1229   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   1230   __ bind(loop_statement.break_label());
   1231   decrement_loop_depth();
   1232 }
   1233 
   1234 
   1235 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
   1236   Comment cmnt(masm_, "[ WhileStatement");
   1237   Label loop, body;
   1238 
   1239   Iteration loop_statement(this, stmt);
   1240   increment_loop_depth();
   1241 
   1242   __ bind(&loop);
   1243 
   1244   SetExpressionAsStatementPosition(stmt->cond());
   1245   VisitForControl(stmt->cond(),
   1246                   &body,
   1247                   loop_statement.break_label(),
   1248                   &body);
   1249 
   1250   PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   1251   __ bind(&body);
   1252   Visit(stmt->body());
   1253 
   1254   __ bind(loop_statement.continue_label());
   1255 
   1256   // Check stack before looping.
   1257   EmitBackEdgeBookkeeping(stmt, &loop);
   1258   __ jmp(&loop);
   1259 
   1260   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   1261   __ bind(loop_statement.break_label());
   1262   decrement_loop_depth();
   1263 }
   1264 
   1265 
   1266 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
   1267   Comment cmnt(masm_, "[ ForStatement");
   1268   // Do not insert break location as we do it below.
   1269   SetStatementPosition(stmt, SKIP_BREAK);
   1270 
   1271   Label test, body;
   1272 
   1273   Iteration loop_statement(this, stmt);
   1274 
   1275   if (stmt->init() != NULL) {
   1276     Visit(stmt->init());
   1277   }
   1278 
   1279   increment_loop_depth();
   1280   // Emit the test at the bottom of the loop (even if empty).
   1281   __ jmp(&test);
   1282 
   1283   PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
   1284   __ bind(&body);
   1285   Visit(stmt->body());
   1286 
   1287   PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
   1288   __ bind(loop_statement.continue_label());
   1289   if (stmt->next() != NULL) {
   1290     SetStatementPosition(stmt->next());
   1291     Visit(stmt->next());
   1292   }
   1293 
   1294   // Check stack before looping.
   1295   EmitBackEdgeBookkeeping(stmt, &body);
   1296 
   1297   __ bind(&test);
   1298   if (stmt->cond() != NULL) {
   1299     SetExpressionAsStatementPosition(stmt->cond());
   1300     VisitForControl(stmt->cond(),
   1301                     &body,
   1302                     loop_statement.break_label(),
   1303                     loop_statement.break_label());
   1304   } else {
   1305     __ jmp(&body);
   1306   }
   1307 
   1308   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   1309   __ bind(loop_statement.break_label());
   1310   decrement_loop_depth();
   1311 }
   1312 
   1313 
   1314 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
   1315   Comment cmnt(masm_, "[ ForOfStatement");
   1316 
   1317   Iteration loop_statement(this, stmt);
   1318   increment_loop_depth();
   1319 
   1320   // var iterator = iterable[Symbol.iterator]();
   1321   SetExpressionAsStatementPosition(stmt->assign_iterator());
   1322   VisitForEffect(stmt->assign_iterator());
   1323 
   1324   // Loop entry.
   1325   __ bind(loop_statement.continue_label());
   1326 
   1327   // result = iterator.next()
   1328   SetExpressionAsStatementPosition(stmt->next_result());
   1329   VisitForEffect(stmt->next_result());
   1330 
   1331   // if (result.done) break;
   1332   Label result_not_done;
   1333   VisitForControl(stmt->result_done(), loop_statement.break_label(),
   1334                   &result_not_done, &result_not_done);
   1335   __ bind(&result_not_done);
   1336 
   1337   // each = result.value
   1338   VisitForEffect(stmt->assign_each());
   1339 
   1340   // Generate code for the body of the loop.
   1341   Visit(stmt->body());
   1342 
   1343   // Check stack before looping.
   1344   PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
   1345   EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
   1346   __ jmp(loop_statement.continue_label());
   1347 
   1348   // Exit and decrement the loop depth.
   1349   PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
   1350   __ bind(loop_statement.break_label());
   1351   decrement_loop_depth();
   1352 }
   1353 
   1354 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
   1355   LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
   1356                      result_register());
   1357   context()->Plug(result_register());
   1358 }
   1359 
   1360 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
   1361   Comment cmnt(masm_, "[ TryCatchStatement");
   1362   SetStatementPosition(stmt, SKIP_BREAK);
   1363 
   1364   // The try block adds a handler to the exception handler chain before
   1365   // entering, and removes it again when exiting normally.  If an exception
   1366   // is thrown during execution of the try block, the handler is consumed
   1367   // and control is passed to the catch block with the exception in the
   1368   // result register.
   1369 
   1370   Label try_entry, handler_entry, exit;
   1371   __ jmp(&try_entry);
   1372   __ bind(&handler_entry);
   1373   if (stmt->clear_pending_message()) ClearPendingMessage();
   1374 
   1375   // Exception handler code, the exception is in the result register.
   1376   // Extend the context before executing the catch block.
   1377   { Comment cmnt(masm_, "[ Extend catch context");
   1378     PushOperand(stmt->variable()->name());
   1379     PushOperand(result_register());
   1380     PushOperand(stmt->scope()->scope_info());
   1381     PushFunctionArgumentForContextAllocation();
   1382     CallRuntimeWithOperands(Runtime::kPushCatchContext);
   1383     StoreToFrameField(StandardFrameConstants::kContextOffset,
   1384                       context_register());
   1385   }
   1386 
   1387   Scope* saved_scope = scope();
   1388   scope_ = stmt->scope();
   1389   DCHECK(scope_->declarations()->is_empty());
   1390   { WithOrCatch catch_body(this);
   1391     Visit(stmt->catch_block());
   1392   }
   1393   // Restore the context.
   1394   LoadContextField(context_register(), Context::PREVIOUS_INDEX);
   1395   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
   1396   scope_ = saved_scope;
   1397   __ jmp(&exit);
   1398 
   1399   // Try block code. Sets up the exception handler chain.
   1400   __ bind(&try_entry);
   1401 
   1402   int handler_index = NewHandlerTableEntry();
   1403   EnterTryBlock(handler_index, &handler_entry, stmt->catch_prediction());
   1404   {
   1405     Comment cmnt_try(masm(), "[ Try block");
   1406     Visit(stmt->try_block());
   1407   }
   1408   ExitTryBlock(handler_index);
   1409   __ bind(&exit);
   1410 }
   1411 
   1412 
   1413 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
   1414   Comment cmnt(masm_, "[ TryFinallyStatement");
   1415   SetStatementPosition(stmt, SKIP_BREAK);
   1416 
   1417   // Try finally is compiled by setting up a try-handler on the stack while
   1418   // executing the try body, and removing it again afterwards.
   1419   //
   1420   // The try-finally construct can enter the finally block in three ways:
   1421   // 1. By exiting the try-block normally. This exits the try block,
   1422   //    pushes the continuation token and falls through to the finally
   1423   //    block.
   1424   // 2. By exiting the try-block with a function-local control flow transfer
   1425   //    (break/continue/return). The site of the, e.g., break exits the
   1426   //    try block, pushes the continuation token and jumps to the
   1427   //    finally block. After the finally block executes, the execution
   1428   //    continues based on the continuation token to a block that
   1429   //    continues with the control flow transfer.
   1430   // 3. By exiting the try-block with a thrown exception. In the handler,
   1431   //    we push the exception and continuation token and jump to the
   1432   //    finally block (which will again dispatch based on the token once
   1433   //    it is finished).
   1434 
   1435   Label try_entry, handler_entry, finally_entry;
   1436   DeferredCommands deferred(this, &finally_entry);
   1437 
   1438   // Jump to try-handler setup and try-block code.
   1439   __ jmp(&try_entry);
   1440   __ bind(&handler_entry);
   1441 
   1442   // Exception handler code.  This code is only executed when an exception
   1443   // is thrown.  Record the continuation and jump to the finally block.
   1444   {
   1445     Comment cmnt_handler(masm(), "[ Finally handler");
   1446     deferred.RecordThrow();
   1447   }
   1448 
   1449   // Set up try handler.
   1450   __ bind(&try_entry);
   1451   int handler_index = NewHandlerTableEntry();
   1452   EnterTryBlock(handler_index, &handler_entry, stmt->catch_prediction());
   1453   {
   1454     Comment cmnt_try(masm(), "[ Try block");
   1455     TryFinally try_body(this, &deferred);
   1456     Visit(stmt->try_block());
   1457   }
   1458   ExitTryBlock(handler_index);
   1459   // Execute the finally block on the way out.  Clobber the unpredictable
   1460   // value in the result register with one that's safe for GC because the
   1461   // finally block will unconditionally preserve the result register on the
   1462   // stack.
   1463   ClearAccumulator();
   1464   deferred.EmitFallThrough();
   1465   // Fall through to the finally block.
   1466 
   1467   // Finally block implementation.
   1468   __ bind(&finally_entry);
   1469   {
   1470     Comment cmnt_finally(masm(), "[ Finally block");
   1471     OperandStackDepthIncrement(2);  // Token and accumulator are on stack.
   1472     EnterFinallyBlock();
   1473     Visit(stmt->finally_block());
   1474     ExitFinallyBlock();
   1475     OperandStackDepthDecrement(2);  // Token and accumulator were on stack.
   1476   }
   1477 
   1478   {
   1479     Comment cmnt_deferred(masm(), "[ Post-finally dispatch");
   1480     deferred.EmitCommands();  // Return to the calling code.
   1481   }
   1482 }
   1483 
   1484 
   1485 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
   1486   Comment cmnt(masm_, "[ DebuggerStatement");
   1487   SetStatementPosition(stmt);
   1488 
   1489   __ DebugBreak();
   1490   // Ignore the return value.
   1491 
   1492   PrepareForBailoutForId(stmt->DebugBreakId(), BailoutState::NO_REGISTERS);
   1493 }
   1494 
   1495 
   1496 void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
   1497   UNREACHABLE();
   1498 }
   1499 
   1500 
   1501 void FullCodeGenerator::VisitConditional(Conditional* expr) {
   1502   Comment cmnt(masm_, "[ Conditional");
   1503   Label true_case, false_case, done;
   1504   VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
   1505 
   1506   int original_stack_depth = operand_stack_depth_;
   1507   PrepareForBailoutForId(expr->ThenId(), BailoutState::NO_REGISTERS);
   1508   __ bind(&true_case);
   1509   SetExpressionPosition(expr->then_expression());
   1510   if (context()->IsTest()) {
   1511     const TestContext* for_test = TestContext::cast(context());
   1512     VisitForControl(expr->then_expression(),
   1513                     for_test->true_label(),
   1514                     for_test->false_label(),
   1515                     NULL);
   1516   } else {
   1517     VisitInDuplicateContext(expr->then_expression());
   1518     __ jmp(&done);
   1519   }
   1520 
   1521   operand_stack_depth_ = original_stack_depth;
   1522   PrepareForBailoutForId(expr->ElseId(), BailoutState::NO_REGISTERS);
   1523   __ bind(&false_case);
   1524   SetExpressionPosition(expr->else_expression());
   1525   VisitInDuplicateContext(expr->else_expression());
   1526   // If control flow falls through Visit, merge it with true case here.
   1527   if (!context()->IsTest()) {
   1528     __ bind(&done);
   1529   }
   1530 }
   1531 
   1532 
   1533 void FullCodeGenerator::VisitLiteral(Literal* expr) {
   1534   Comment cmnt(masm_, "[ Literal");
   1535   context()->Plug(expr->value());
   1536 }
   1537 
   1538 
   1539 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
   1540   Comment cmnt(masm_, "[ FunctionLiteral");
   1541 
   1542   // Build the function boilerplate and instantiate it.
   1543   Handle<SharedFunctionInfo> function_info =
   1544       Compiler::GetSharedFunctionInfo(expr, script(), info_);
   1545   if (function_info.is_null()) {
   1546     SetStackOverflow();
   1547     return;
   1548   }
   1549   EmitNewClosure(function_info, expr->pretenure());
   1550 }
   1551 
   1552 
   1553 void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
   1554   Comment cmnt(masm_, "[ ClassLiteral");
   1555 
   1556   if (lit->extends() != NULL) {
   1557     VisitForStackValue(lit->extends());
   1558   } else {
   1559     PushOperand(isolate()->factory()->the_hole_value());
   1560   }
   1561 
   1562   VisitForStackValue(lit->constructor());
   1563 
   1564   PushOperand(Smi::FromInt(lit->start_position()));
   1565   PushOperand(Smi::FromInt(lit->end_position()));
   1566 
   1567   CallRuntimeWithOperands(Runtime::kDefineClass);
   1568   PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
   1569   PushOperand(result_register());
   1570 
   1571   // Load the "prototype" from the constructor.
   1572   __ Move(LoadDescriptor::ReceiverRegister(), result_register());
   1573   CallLoadIC(lit->PrototypeSlot(), isolate()->factory()->prototype_string());
   1574   PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
   1575   PushOperand(result_register());
   1576 
   1577   EmitClassDefineProperties(lit);
   1578   DropOperands(1);
   1579 
   1580   // Set the constructor to have fast properties.
   1581   CallRuntimeWithOperands(Runtime::kToFastProperties);
   1582 
   1583   if (lit->class_variable_proxy() != nullptr) {
   1584     EmitVariableAssignment(lit->class_variable_proxy()->var(), Token::INIT,
   1585                            lit->ProxySlot(), HoleCheckMode::kElided);
   1586   }
   1587 
   1588   context()->Plug(result_register());
   1589 }
   1590 
   1591 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
   1592   Comment cmnt(masm_, "[ RegExpLiteral");
   1593   Callable callable = CodeFactory::FastCloneRegExp(isolate());
   1594   CallInterfaceDescriptor descriptor = callable.descriptor();
   1595   LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
   1596                      descriptor.GetRegisterParameter(0));
   1597   __ Move(descriptor.GetRegisterParameter(1),
   1598           Smi::FromInt(expr->literal_index()));
   1599   __ Move(descriptor.GetRegisterParameter(2), expr->pattern());
   1600   __ Move(descriptor.GetRegisterParameter(3), Smi::FromInt(expr->flags()));
   1601   __ Call(callable.code(), RelocInfo::CODE_TARGET);
   1602 
   1603   // Reload the context register after the call as i.e. TurboFan code stubs
   1604   // won't preserve the context register.
   1605   LoadFromFrameField(StandardFrameConstants::kContextOffset,
   1606                      context_register());
   1607   context()->Plug(result_register());
   1608 }
   1609 
   1610 void FullCodeGenerator::VisitNativeFunctionLiteral(
   1611     NativeFunctionLiteral* expr) {
   1612   Comment cmnt(masm_, "[ NativeFunctionLiteral");
   1613   Handle<SharedFunctionInfo> shared =
   1614       Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
   1615   EmitNewClosure(shared, false);
   1616 }
   1617 
   1618 
   1619 void FullCodeGenerator::VisitThrow(Throw* expr) {
   1620   Comment cmnt(masm_, "[ Throw");
   1621   VisitForStackValue(expr->exception());
   1622   SetExpressionPosition(expr);
   1623   CallRuntimeWithOperands(Runtime::kThrow);
   1624   // Never returns here.
   1625 
   1626   // Even though this expression doesn't produce a value, we need to simulate
   1627   // plugging of the value context to ensure stack depth tracking is in sync.
   1628   if (context()->IsStackValue()) OperandStackDepthIncrement(1);
   1629 }
   1630 
   1631 void FullCodeGenerator::EnterTryBlock(
   1632     int handler_index, Label* handler,
   1633     HandlerTable::CatchPrediction catch_prediction) {
   1634   HandlerTableEntry* entry = &handler_table_[handler_index];
   1635   entry->range_start = masm()->pc_offset();
   1636   entry->handler_offset = handler->pos();
   1637   entry->stack_depth = operand_stack_depth_;
   1638   entry->catch_prediction = catch_prediction;
   1639 
   1640   // We are using the operand stack depth, check for accuracy.
   1641   EmitOperandStackDepthCheck();
   1642 
   1643   // Push context onto operand stack.
   1644   STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
   1645   PushOperand(context_register());
   1646 }
   1647 
   1648 
   1649 void FullCodeGenerator::ExitTryBlock(int handler_index) {
   1650   HandlerTableEntry* entry = &handler_table_[handler_index];
   1651   entry->range_end = masm()->pc_offset();
   1652 
   1653   // Drop context from operand stack.
   1654   DropOperands(TryBlockConstant::kElementCount);
   1655 }
   1656 
   1657 
   1658 void FullCodeGenerator::VisitCall(Call* expr) {
   1659 #ifdef DEBUG
   1660   // We want to verify that RecordJSReturnSite gets called on all paths
   1661   // through this function.  Avoid early returns.
   1662   expr->return_is_recorded_ = false;
   1663 #endif
   1664 
   1665   Comment cmnt(masm_, (expr->tail_call_mode() == TailCallMode::kAllow)
   1666                           ? "[ TailCall"
   1667                           : "[ Call");
   1668   Expression* callee = expr->expression();
   1669   Call::CallType call_type = expr->GetCallType();
   1670 
   1671   if (expr->is_possibly_eval()) {
   1672     EmitPossiblyEvalCall(expr);
   1673   } else {
   1674     switch (call_type) {
   1675       case Call::GLOBAL_CALL:
   1676         EmitCallWithLoadIC(expr);
   1677         break;
   1678       case Call::WITH_CALL:
   1679         // Call to a lookup slot looked up through a with scope.
   1680         PushCalleeAndWithBaseObject(expr);
   1681         EmitCall(expr);
   1682         break;
   1683       case Call::NAMED_PROPERTY_CALL: {
   1684         Property* property = callee->AsProperty();
   1685         VisitForStackValue(property->obj());
   1686         EmitCallWithLoadIC(expr);
   1687         break;
   1688       }
   1689       case Call::KEYED_PROPERTY_CALL: {
   1690         Property* property = callee->AsProperty();
   1691         VisitForStackValue(property->obj());
   1692         EmitKeyedCallWithLoadIC(expr, property->key());
   1693         break;
   1694       }
   1695       case Call::NAMED_SUPER_PROPERTY_CALL:
   1696         EmitSuperCallWithLoadIC(expr);
   1697         break;
   1698       case Call::KEYED_SUPER_PROPERTY_CALL:
   1699         EmitKeyedSuperCallWithLoadIC(expr);
   1700         break;
   1701       case Call::SUPER_CALL:
   1702         EmitSuperConstructorCall(expr);
   1703         break;
   1704       case Call::OTHER_CALL:
   1705         // Call to an arbitrary expression not handled specially above.
   1706         VisitForStackValue(callee);
   1707         OperandStackDepthIncrement(1);
   1708         __ PushRoot(Heap::kUndefinedValueRootIndex);
   1709         // Emit function call.
   1710         EmitCall(expr);
   1711         break;
   1712     }
   1713   }
   1714 
   1715 #ifdef DEBUG
   1716   // RecordJSReturnSite should have been called.
   1717   DCHECK(expr->return_is_recorded_);
   1718 #endif
   1719 }
   1720 
   1721 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
   1722   ZoneList<Expression*>* args = expr->arguments();
   1723   int arg_count = args->length();
   1724 
   1725   if (expr->is_jsruntime()) {
   1726     Comment cmnt(masm_, "[ CallRuntime");
   1727     EmitLoadJSRuntimeFunction(expr);
   1728 
   1729     // Push the arguments ("left-to-right").
   1730     for (int i = 0; i < arg_count; i++) {
   1731       VisitForStackValue(args->at(i));
   1732     }
   1733 
   1734     PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   1735     EmitCallJSRuntimeFunction(expr);
   1736     context()->DropAndPlug(1, result_register());
   1737 
   1738   } else {
   1739     const Runtime::Function* function = expr->function();
   1740     switch (function->function_id) {
   1741 #define CALL_INTRINSIC_GENERATOR(Name)     \
   1742   case Runtime::kInline##Name: {           \
   1743     Comment cmnt(masm_, "[ Inline" #Name); \
   1744     return Emit##Name(expr);               \
   1745   }
   1746       FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
   1747 #undef CALL_INTRINSIC_GENERATOR
   1748       default: {
   1749         Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
   1750         // Push the arguments ("left-to-right").
   1751         for (int i = 0; i < arg_count; i++) {
   1752           VisitForStackValue(args->at(i));
   1753         }
   1754 
   1755         // Call the C runtime function.
   1756         PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
   1757         __ CallRuntime(expr->function(), arg_count);
   1758         OperandStackDepthDecrement(arg_count);
   1759         context()->Plug(result_register());
   1760       }
   1761     }
   1762   }
   1763 }
   1764 
   1765 void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
   1766 
   1767 
   1768 void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
   1769   UNREACHABLE();
   1770 }
   1771 
   1772 
   1773 void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
   1774   Visit(expr->expression());
   1775 }
   1776 
   1777 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
   1778     int* context_length) {
   1779   // The macros used here must preserve the result register.
   1780 
   1781   // Calculate how many operands to drop to get down to handler block.
   1782   int stack_drop = codegen_->operand_stack_depth_ - GetStackDepthAtTarget();
   1783   DCHECK_GE(stack_drop, 0);
   1784 
   1785   // Because the handler block contains the context of the finally
   1786   // code, we can restore it directly from there for the finally code
   1787   // rather than iteratively unwinding contexts via their previous
   1788   // links.
   1789   if (*context_length > 0) {
   1790     __ Drop(stack_drop);  // Down to the handler block.
   1791     // Restore the context to its dedicated register and the stack.
   1792     STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
   1793     __ Pop(codegen_->context_register());
   1794     codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
   1795                                 codegen_->context_register());
   1796   } else {
   1797     // Down to the handler block and also drop context.
   1798     __ Drop(stack_drop + TryBlockConstant::kElementCount);
   1799   }
   1800 
   1801   // The caller will ignore outputs.
   1802   *context_length = -1;
   1803   return previous_;
   1804 }
   1805 
   1806 void FullCodeGenerator::DeferredCommands::RecordBreak(Statement* target) {
   1807   TokenId token = dispenser_.GetBreakContinueToken();
   1808   commands_.push_back({kBreak, token, target});
   1809   EmitJumpToFinally(token);
   1810 }
   1811 
   1812 void FullCodeGenerator::DeferredCommands::RecordContinue(Statement* target) {
   1813   TokenId token = dispenser_.GetBreakContinueToken();
   1814   commands_.push_back({kContinue, token, target});
   1815   EmitJumpToFinally(token);
   1816 }
   1817 
   1818 void FullCodeGenerator::DeferredCommands::RecordReturn() {
   1819   if (return_token_ == TokenDispenserForFinally::kInvalidToken) {
   1820     return_token_ = TokenDispenserForFinally::kReturnToken;
   1821     commands_.push_back({kReturn, return_token_, nullptr});
   1822   }
   1823   EmitJumpToFinally(return_token_);
   1824 }
   1825 
   1826 void FullCodeGenerator::DeferredCommands::RecordThrow() {
   1827   if (throw_token_ == TokenDispenserForFinally::kInvalidToken) {
   1828     throw_token_ = TokenDispenserForFinally::kThrowToken;
   1829     commands_.push_back({kThrow, throw_token_, nullptr});
   1830   }
   1831   EmitJumpToFinally(throw_token_);
   1832 }
   1833 
   1834 void FullCodeGenerator::DeferredCommands::EmitFallThrough() {
   1835   __ Push(Smi::FromInt(TokenDispenserForFinally::kFallThroughToken));
   1836   __ Push(result_register());
   1837 }
   1838 
   1839 void FullCodeGenerator::DeferredCommands::EmitJumpToFinally(TokenId token) {
   1840   __ Push(Smi::FromInt(token));
   1841   __ Push(result_register());
   1842   __ jmp(finally_entry_);
   1843 }
   1844 
   1845 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
   1846   Expression* sub_expr;
   1847   Handle<String> check;
   1848   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
   1849     SetExpressionPosition(expr);
   1850     EmitLiteralCompareTypeof(expr, sub_expr, check);
   1851     return true;
   1852   }
   1853 
   1854   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
   1855     SetExpressionPosition(expr);
   1856     EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   1857     return true;
   1858   }
   1859 
   1860   if (expr->IsLiteralCompareNull(&sub_expr)) {
   1861     SetExpressionPosition(expr);
   1862     EmitLiteralCompareNil(expr, sub_expr, kNullValue);
   1863     return true;
   1864   }
   1865 
   1866   return false;
   1867 }
   1868 
   1869 
   1870 void BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) {
   1871   DisallowHeapAllocation no_gc;
   1872   Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
   1873 
   1874   // Increment loop nesting level by one and iterate over the back edge table
   1875   // to find the matching loops to patch the interrupt
   1876   // call to an unconditional call to the replacement code.
   1877   int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
   1878   if (loop_nesting_level > AbstractCode::kMaxLoopNestingMarker) return;
   1879 
   1880   BackEdgeTable back_edges(unoptimized, &no_gc);
   1881   for (uint32_t i = 0; i < back_edges.length(); i++) {
   1882     if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
   1883       DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate,
   1884                                             unoptimized,
   1885                                             back_edges.pc(i)));
   1886       PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
   1887     }
   1888   }
   1889 
   1890   unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
   1891   DCHECK(Verify(isolate, unoptimized));
   1892 }
   1893 
   1894 
   1895 void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) {
   1896   DisallowHeapAllocation no_gc;
   1897   Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
   1898 
   1899   // Iterate over the back edge table and revert the patched interrupt calls.
   1900   int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
   1901 
   1902   BackEdgeTable back_edges(unoptimized, &no_gc);
   1903   for (uint32_t i = 0; i < back_edges.length(); i++) {
   1904     if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
   1905       DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate,
   1906                                             unoptimized,
   1907                                             back_edges.pc(i)));
   1908       PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
   1909     }
   1910   }
   1911 
   1912   unoptimized->set_allow_osr_at_loop_nesting_level(0);
   1913   // Assert that none of the back edges are patched anymore.
   1914   DCHECK(Verify(isolate, unoptimized));
   1915 }
   1916 
   1917 
   1918 #ifdef DEBUG
   1919 bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
   1920   DisallowHeapAllocation no_gc;
   1921   int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
   1922   BackEdgeTable back_edges(unoptimized, &no_gc);
   1923   for (uint32_t i = 0; i < back_edges.length(); i++) {
   1924     uint32_t loop_depth = back_edges.loop_depth(i);
   1925     CHECK_LE(static_cast<int>(loop_depth), AbstractCode::kMaxLoopNestingMarker);
   1926     // Assert that all back edges for shallower loops (and only those)
   1927     // have already been patched.
   1928     CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
   1929              GetBackEdgeState(isolate,
   1930                               unoptimized,
   1931                               back_edges.pc(i)) != INTERRUPT);
   1932   }
   1933   return true;
   1934 }
   1935 #endif  // DEBUG
   1936 
   1937 
   1938 FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
   1939     FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
   1940     BailoutId declarations_id, BailoutId exit_id)
   1941     : codegen_(codegen), exit_id_(exit_id) {
   1942   saved_scope_ = codegen_->scope();
   1943 
   1944   if (scope == NULL) {
   1945     codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
   1946     needs_block_context_ = false;
   1947   } else {
   1948     needs_block_context_ = scope->NeedsContext();
   1949     codegen_->scope_ = scope;
   1950     {
   1951       if (needs_block_context_) {
   1952         Comment cmnt(masm(), "[ Extend block context");
   1953         codegen_->PushOperand(scope->scope_info());
   1954         codegen_->PushFunctionArgumentForContextAllocation();
   1955         codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext);
   1956 
   1957         // Replace the context stored in the frame.
   1958         codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
   1959                                     codegen_->context_register());
   1960       }
   1961       CHECK_EQ(0, scope->num_stack_slots());
   1962       codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
   1963     }
   1964     {
   1965       Comment cmnt(masm(), "[ Declarations");
   1966       codegen_->VisitDeclarations(scope->declarations());
   1967       codegen_->PrepareForBailoutForId(declarations_id,
   1968                                        BailoutState::NO_REGISTERS);
   1969     }
   1970   }
   1971 }
   1972 
   1973 
   1974 FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
   1975   if (needs_block_context_) {
   1976     codegen_->LoadContextField(codegen_->context_register(),
   1977                                Context::PREVIOUS_INDEX);
   1978     // Update local stack frame context field.
   1979     codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
   1980                                 codegen_->context_register());
   1981   }
   1982   codegen_->PrepareForBailoutForId(exit_id_, BailoutState::NO_REGISTERS);
   1983   codegen_->scope_ = saved_scope_;
   1984 }
   1985 
   1986 Handle<Script> FullCodeGenerator::script() { return info_->script(); }
   1987 
   1988 LanguageMode FullCodeGenerator::language_mode() {
   1989   return scope()->language_mode();
   1990 }
   1991 
   1992 bool FullCodeGenerator::has_simple_parameters() {
   1993   return info_->has_simple_parameters();
   1994 }
   1995 
   1996 FunctionLiteral* FullCodeGenerator::literal() const { return info_->literal(); }
   1997 
   1998 #undef __
   1999 
   2000 
   2001 }  // namespace internal
   2002 }  // namespace v8
   2003