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